持续集成
Travis CI
Travis 是一项用于在云端运行单元测试的服务。你发起的每次提交和针对项目的每个拉取请求 Travis 都会看到,它会启动一个 Docker 容器并运行你的测试。改进配置后,它就可以支持 Common Lisp。
Travis 由你的仓库根目录中的一个文件 .travis.yml
进行控制。它定义了一些选项,如:项目使用的 language
、在运行测试前必须执行的 shell 命令列表以及向何处发送通知。
YAML 是一种结构化数据的易读格式。Ansible、Chef 和 Salt 等工具让它成为配置管理和部署的常用选择。结果其实是一个 shell 脚本,只不过它被构建到不同的部分。
若要测试 Common Lisp 项目,我们使用 cl-travis。它提供了一个脚本,可让 Travis 下载该脚本,这个脚本会设置你选择的 Common Lisp 实现(你可以在很多实现上进行测试 – 如下)。
不用多说,以下是最简单的 .travis.yml
的样子
language: common-lisp
sudo: required
env:
matrix:
- LISP=sbcl
- LISP=ccl
install:
# Install cl-travis
- curl https://raw.githubusercontent.com/luismbo/cl-travis/master/install.sh | bash
script:
- cl -l fiveam
-e '(setf fiveam:*debug-on-error* t
fiveam:*debug-on-failure* t)'
-e '(setf *debugger-hook*
(lambda (c h)
(declare (ignore c h))
(uiop:quit -1)))'
-e '(ql:quickload :my-project-test)'
notifications:
email:
- my-email@gmail.com
前两项只是定义项目的语言,并告诉它运行测试需要 sudo
。cl-travis
需要 sudo,所以至少现在我们必须将它设置为 required
。
env.matrix
列表的每一项都会使用特定环境变量配置创建一个新构建。在此示例中,我们希望在 SBCL 和 CCL 上进行测试,所以我们使用此列表
env:
matrix:
- LISP=sbcl
- LISP=ccl
install
列表只是一些 shell 命令的列表,用于执行来设置测试环境。在此,我们只是下载和安装 cl-travis
install:
# Install cl-travis
- curl https://raw.githubusercontent.com/luismbo/cl-travis/master/install.sh | bash
需要系统库才能运行测试的项目,例如 Crane,可以在 install
列表中安装和配置这些库
install:
# Install cl-travis
- curl https://raw.githubusercontent.com/luismbo/cl-travis/master/install.sh | bash
# Install the latest versions of the major dependencies
- git clone https://github.com/fukamachi/sxql.git quicklisp/local-projects/sxql
- git clone https://github.com/fukamachi/cl-dbi.git quicklisp/local-projects/cl-dbi
# Update package repos
- sudo apt-get update
# Install SQLite
- sudo apt-get install -y sqlite3
# Set up Postgres
- sudo -u postgres createdb crane_test_db
- sudo -u postgres psql -c "CREATE USER crane_test_user WITH PASSWORD 'crane_test_user'"
- sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE crane_test_db TO crane_test_user"
对于你想使用最新版本的依赖项进行测试的项目,你可以将它们克隆到 ~/lisp
文件夹中。例如,这是 Scriba 的 .travis.yml
文件的 install
列表
install:
# Install cl-travis
- curl https://raw.githubusercontent.com/luismbo/cl-travis/master/install.sh | bash
# Clone the latest common-doc
- git clone https://github.com/CommonDoc/common-doc.git ~/lisp/common-doc
# Clone the latest common-doc-plump
- git clone https://github.com/CommonDoc/common-doc-plump.git ~/lisp/common-doc-plump
最后,script
是实际测试本身。 cl-travis
安装 CIM,这是一种命令行实用工具,用于在一个通用界面下管理和运行不同的 Lisp 实现。
cl
命令启动一个 Lisp 映像,-l
标志可以用来快速加载一个库。 -e
标志让我们执行代码,在这里我们设置在发生故障时执行什么操作以及如何运行测试。
如果你使用 FiveAM 进行测试,你需要告诉它在测试失败和错误时进入调试器。然后,将调试器连接到 UIOP 的1 与实现无关的 quit
函数。这可确保在测试失败时,脚本会以 -1
退出,这告诉 Travis 测试已失败。然后,我们只需要快速加载测试系统来运行测试
script:
- cl -l fiveam
-e '(setf fiveam:*debug-on-error* t
fiveam:*debug-on-failure* t)'
-e '(setf *debugger-hook*
(lambda (c h)
(declare (ignore c h))
(uiop:quit -1)))'
-e '(ql:quickload :my-project-test)'
如果你使用 fukamachi 的 prove 进行测试,则使用此命令
script:
- cl -l prove -e '(or (prove:run :my-project-test) (uiop:quit -1))'
启用 Travis
要使用 Travis,你需要用你的 GitHub 帐户注册。然后将鼠标悬停在页面右上角的你的名字上,并转到你的个人资料页面。这将向你显示以下页面
如果你刚刚推送了存储库,那么你可能需要点击“同步”来更新存储库列表。
然后,你点击存储库名称旁边的开关来启用它,然后你所要做的就是推送一个提交以触发构建。Travis 与所有服务一样,在可用性方面有其优缺点。因此,有时构建会几乎立即开始,而其他时候则需要更长时间。
Gitlab CI 和 Docker
Gitlab CI 是 Gitlab 的一部分,可在 Gitlab.com 上使用,适用于公共存储库和私人存储库。我们立刻来看一个简单的 .gitlab-ci.yml
image: daewok/lisp-devel
before_script:
- apt-get update -qy
- apt-get install -y git-core
- git clone https://github.com/foo/bar ~/quicklisp/local-projects/
test:
script:
- make test
Gitlab CI 基于 Docker。使用 image
,我们告诉它使用 daewok/lisp-devel 镜像。它包括 SBCL、ECL、CCL 和 ABCL,并且 Quicklisp 已安装在主页 (/home/lisp/
) 中,因此我们可以立即 quickload
软件包。如果你有兴趣,它还有一个更基本的选项。Gitlab 将加载镜像,克隆我们的项目并将我们放在项目根目录中,并具有运行其余命令的管理权限。
test
是我们定义的一个“作业”, script
是一个已识别的关键字,它采用要运行的命令列表。
假设我们必须在运行测试之前安装依赖项:before_script
将在每个作业之前运行。在该示例中,我们在 Quicklisp 可以找到该库的位置克隆一个库,为此,我们必须安装 git(Docker 镜像通常都很精简)。
我们可以在本地亲自尝试。如果我们已经安装 Docker 并启动了它的守护进程 (sudo service docker start
),我们可以执行
docker run --rm -it -v /path/to/local/code:/usr/local/share/common-lisp/source daewok/lisp-devel:latest bash
这将下载 lisp 镜像 (±400Mo),将一些本地代码装载到所示的镜像中,并将我们放入 bash。现在,我们可以尝试 make test
。
向您展示一个更完整的示例
image: daewok/lisp-devel
stages:
- test
- build
before_script:
- apt-get update -qy
- apt-get install -y git-core
- git clone https://github.com/foo/bar ~/quicklisp/local-projects/
test:
stage: test
script:
- make test
build:
stage: build
only:
- tags
script:
- make build
artifacts:
paths:
- some-file-name
在该示例中,我们定义了两个 stages
(请参阅 environments),即“test”和“build”,被定义为一个接一个运行。“build”阶段仅在“test”阶段成功后才会启动。
仅当推送新标记时,才要求“build”运行 only
,而不是在每次提交时。成功后,它会提供 artifacts
的 paths
中列出的文件,以便下载。我们可以从 Gitlab 的 Pipelines UI 或通过 URL 下载它们。该网址将下载最新“build”作业中的“some-file-name”文件
https://gitlab.com/username/project-name/-/jobs/artifacts/master/raw/some-file-name?job=build
当管道通过时,您会看到
你现在拥有一个可用于 Gitlab CI。
- 来源:CL Cookbook
覆盖率跟踪
代码覆盖率基本上是指有多少行源代码是由测试运行的。SBCL 支持覆盖率测量,并且可以生成一些 HTML 覆盖率报告,但这需要一些手动操作。
进入 Coveralls:这是一项获取原始代码覆盖率数据并进行跟踪的服务。它向您展示已覆盖的文件、执行了哪些行以及哪些行未执行、一段时间内的覆盖率演化,还会告诉您拉取请求对覆盖率的影响。
Coveralls 与 Travis 协作,因此无需其他文件:您在 Travis 编译中运行代码覆盖率(以及测试),并将数据发送至 Coveralls 以进行跟踪。实现所有这些的库是 cl-coveralls,它提供了一个宏,用覆盖率测量包装一些代码。
若要将 Coveralls 支持添加到 .travis.yml
文件,我们首先将 COVERALLS
环境变量设置为某一特定实现(最好是 SBCL)的 true
env:
matrix:
- LISP=sbcl COVERALLS=true
- LISP=ccl
然后,我们克隆 cl-coveralls
install:
# Coveralls support
- git clone https://github.com/fukamachi/cl-coveralls ~/lisp/cl-coveralls
在 脚本
中,我们加载 Coveralls 以及我们的测试框架,然后将运行测试的代码包装在 with-coveralls
macro 中。
script:
- cl -l fiveam -l cl-coveralls
-e '(setf fiveam:*debug-on-error* t
fiveam:*debug-on-failure* t)'
-e '(setf *debugger-hook*
(lambda (c h)
(declare (ignore c h))
(uiop:quit -1)))'
-e '(coveralls:with-coveralls (:exclude (list "t"))
(ql:quickload :my-project-test))'
请注意我们如何使用 :exclude
选项来防止测试代码落入覆盖率跟踪。
启用 Coveralls
此过程类似于为 Travis 启用存储库。
点击开关以启用或禁用存储库,如果存储库是新的,请单击页面顶部附近的“同步 GitHub 存储库”。
徽章
现在,这样做的目的是让用户知道软件处于什么状态。Travis 和 Coveralls 都给每个项目一个状态徽章,图像可以放在 README 中,让用户预先知道项目的可用状态和覆盖率状态。
以下是 Travis 和 Coveralls 徽章的 Markdown
# Project Name
[](https://travis-ci.org/USER/REPO)
[](https://coveralls.io/r/USER/REPO?branch=master)
项目
下面是一个使用 Travis 和/或 Coveralls 的项目(必然不完整)列表