持续集成

Travis CI

Travis 是一项用于在云端运行单元测试的服务。你发起的每次提交和针对项目的每个拉取请求 Travis 都会看到,它会启动一个 Docker 容器并运行你的测试。改进配置后,它就可以支持 Common Lisp。

Travis 由你的仓库根目录中的一个文件 .travis.yml 进行控制。它定义了一些选项,如:项目使用的 language、在运行测试前必须执行的 shell 命令列表以及向何处发送通知。

YAML 是一种结构化数据的易读格式。AnsibleChefSalt 等工具让它成为配置管理和部署的常用选择。结果其实是一个 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

前两项只是定义项目的语言,并告诉它运行测试需要 sudocl-travis 需要 sudo,所以至少现在我们必须将它设置为 required

env.matrix 列表的每一项都会使用特定环境变量配置创建一个新构建。在此示例中,我们希望在 SBCLCCL 上进行测试,所以我们使用此列表

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 profile page

如果你刚刚推送了存储库,那么你可能需要点击“同步”来更新存储库列表。

然后,你点击存储库名称旁边的开关来启用它,然后你所要做的就是推送一个提交以触发构建。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,而不是在每次提交时。成功后,它会提供 artifactspaths 中列出的文件,以便下载。我们可以从 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。

覆盖率跟踪

代码覆盖率基本上是指有多少行源代码是由测试运行的。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 启用存储库。

Coveralls profile page

点击开关以启用或禁用存储库,如果存储库是新的,请单击页面顶部附近的“同步 GitHub 存储库”。

徽章

现在,这样做的目的是让用户知道软件处于什么状态。Travis 和 Coveralls 都给每个项目一个状态徽章,图像可以放在 README 中,让用户预先知道项目的可用状态和覆盖率状态。

以下是 Travis 和 Coveralls 徽章的 Markdown

# Project Name

[![Build Status](https://travis-ci.org/USER/REPO.svg?branch=master)](https://travis-ci.org/USER/REPO)
[![Coverage Status](https://coveralls.io/repos/USER/REPO/badge.svg?branch=master)](https://coveralls.io/r/USER/REPO?branch=master)

项目

下面是一个使用 Travis 和/或 Coveralls 的项目(必然不完整)列表

脚注

  1. 这是 ASDF 的可移植工具层。它提供了一些非常有用的内容,例如以可靠且可移植的方式查找主机名、退出 Lisp 映像或查找系统架构。