持續(xù)集成是一種軟件開發(fā)實踐丈甸,每次集成都通過自動化的構(gòu)建(包括編譯,發(fā)布顶霞,自動化測試)來驗證肄程,從而盡快地發(fā)現(xiàn)集成錯誤,大大減少集成的問題选浑,讓團隊能夠更快的開發(fā)內(nèi)聚的軟件蓝厌。
實現(xiàn)目標(biāo)
單元測試作為持續(xù)集成的一部分,下面我們借助gitlab的CI能力來實現(xiàn)以下目標(biāo):
- 每個開發(fā)人員在各自開發(fā)分支開發(fā)古徒,每當(dāng)提交代碼后自動觸發(fā)單元測試
- 開發(fā)完成后由開發(fā)人員發(fā)起merge request并觸發(fā)單元測試褂始,如果單元測試不通過則不允許合并
- 如果單元測試通過并code review后沒問題則允許代碼合并
實驗環(huán)境:
php:7.4
phpunit: 9.5.9
gitlab: 14.2.4-ee
創(chuàng)建Gitlab項目及單元測試代碼準(zhǔn)備
在gitlab上創(chuàng)建一個cicd-php的PHP代碼用于測試
單元測試具體如何編寫可參考文章:PHP單元測試基礎(chǔ)實踐(PHPUnit)
在此項目中我們利用composer安裝了phpunit來對PHP的代碼進行單元測試,安裝完成后在項目根目錄的vendor/bin/目錄會出現(xiàn)phpunit的可執(zhí)行文件
$ composer require --dev phpunit/phpunit
項目目錄結(jié)構(gòu)如下:
├── app
│ └── Service
│ └── MyLogic.php
├── test
│ ├── bootstrap.php
│ └── unit
│ └── MyLogicTest.php
├── composer.json
├── composer.lock
├── phpunit.xml
└── vendor
app/Service/MyLogic.php : 假設(shè)為要測試的業(yè)務(wù)邏輯,以下寫了一個簡單的加法函數(shù)用于測試
<?php
namespace App\Service;
class MyLogic
{
public function add($num1, $num2)
{
return $num1 + $num2;
}
}
test/unit/MyLogicTest.php : 為MyLogic類的單元測試
<?php
namespace Test\unit\Service;
use App\Service\MyLogic;
use PHPUnit\Framework\TestCase;
class MyLogicTest extends TestCase
{
public function testAdd()
{
$logic = new MyLogic();
$ret = $logic->add(1, 1);
$this->assertSame($ret, 2);
}
}
通過執(zhí)行phpunit執(zhí)行單元測試描函,通過以下輸出可看出執(zhí)行了一個單元測試并且執(zhí)行成功
$ ./vendor/bin/phpunit -c ./phpunit.xml
PHPUnit 9.5.9 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 00:00.009, Memory: 6.00 MB
OK (1 test, 1 assertion)
配置Gitlab-CI功能 及 Gitlab-runner
GitLab-CI:就是一套配合GitLab使用的持續(xù)集成系統(tǒng)
GitLab-Runner:是配合GitLab-CI進行使用的崎苗。用來自動化執(zhí)行軟件集成腳本的進程。當(dāng)這個工程的倉庫代碼發(fā)生變動時舀寓,比如有人push了代碼胆数,GitLab就會將這個變動通知GitLab-CI。這時GitLab-CI會找出與這個工程相關(guān)聯(lián)的Runner互墓,并通知這些Runner把代碼更新到本地并執(zhí)行預(yù)定義好的執(zhí)行腳本必尼。
Runner就像一個個的工人,而GitLab-CI就是這些工人的一個管理中心篡撵,所有工人都要在GitLab-CI里面登記注冊判莉,并且表明自己是為哪個工程服務(wù)的。當(dāng)相應(yīng)的工程發(fā)生變化時育谬,GitLab-CI就會通知相應(yīng)的工人執(zhí)行軟件集成腳本券盅。
安裝Gitlab-runner并注冊
- 安裝docker
$ yum install docker
- 安裝gitlab-runner
可以從gitlab上獲取runner所需的URL和注冊token,路徑為Settings > CI/CD > Runners settings
#拉取gitlab-runner鏡像
$ docker pull gitlab/gitlab-runner
#啟動gitlab-runner
$ docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
--network=host \
docker.io/gitlab/gitlab-runner
# 進去容器
$ docker exec -it gitlab-runner bash
# 執(zhí)行注冊gitlab-runner命令膛檀,此處按提示輸入相關(guān)的參數(shù)即可
$ gitlab-runner register
注冊后在gitlab可以看到runner
注:如果宿主機沒有開啟ipv4轉(zhuǎn)發(fā)锰镀,那么docker的bridge網(wǎng)絡(luò)將不能訪問外網(wǎng),開啟ipv4轉(zhuǎn)可參考以下步驟
#配置轉(zhuǎn)發(fā)
$ vim /etc/sysctl.conf
net.ipv4.ip_forward=1
# 重啟網(wǎng)絡(luò)
$ systemctl restart network
#查看是否成功,以下命令如果返回1則表示成功
$ sysctl net.ipv4.ip_forward
配置Gitlab-CI配置文件
為了利用gitlab的持續(xù)集成能力咖刃,我們可以通過在項目根目錄寫一個.gitlab-ci.yml配置文件來開啟gitlab pipeline功能
stages:
- test
job1:
stage: test
tags:
- cicd
only:
- main
- merge_requests
script:
- ./vendor/bin/phpunit -c ./phpunit.xml
注:merge_requests 的功能在gitlab 11.6之后的版本才支持
每當(dāng)main分支提交代碼時泳炉,并會觸發(fā)一個pipeline任務(wù)進行自動化構(gòu)建
pending:表示任務(wù)執(zhí)行中
failed:表示任務(wù)執(zhí)行失敗
passed:表示任務(wù)執(zhí)行成功
以下我們新建一個test分支,并將MyLogicTest的斷言改為失敗的斷言嚎杨,來測試test分支merge_request到main分支花鹅,單測失敗的場景
<?php
namespace Test\unit\Service;
use App\Service\MyLogic;
use PHPUnit\Framework\TestCase;
class MyLogicTest extends TestCase
{
public function testAdd()
{
$logic = new MyLogic();
$ret = $logic->add(1, 1);
$this->assertSame($ret, 3);
}
}
在gitlab發(fā)起merge request
創(chuàng)建merge request后會自動觸發(fā)一個pipeline進行構(gòu)建
如果pipeline執(zhí)行失敗會顯示一個紅色的x
接下來我們在test分支將單元測試斷言修改為正確并提交,會發(fā)現(xiàn)原來的merge request的狀態(tài)重新變?yōu)閳?zhí)行中枫浙,點擊“merge when pipeline succeeds”則表示當(dāng)pipeline執(zhí)行成功后則自動合并代碼
當(dāng)pipeline執(zhí)行成功后刨肃,則表示該merge request的代碼已經(jīng)通過了單元測試古拴,點擊“Merge”按鈕就可以將分支代碼合并到目標(biāo)分支