在持续集成构建中无头运行 JavaScript 单元测试

我有一个在持续集成系统上运行的 webapp 构建计划(Atlassian Bamboo 2.5).我需要将基于 QUnit 的 JavaScript 单元测试合并到构建计划中,以便在每次构建时,Javascript 测试将运行,Bamboo 将解释测试结果.

最好我希望能够使构建过程独立",这样就不需要连接到外部服务器.关于如何实现这一点的好主意?运行构建过程的 CI 系统位于 Ubuntu Linux 服务器上.

解决方案

我自己想出了一个解决方案,我认为分享它是个好主意.这种方法可能并非完美无缺,但它似乎是第一个有效的方法.随时发布改进和建议.

简而言之我做了什么:

  • 启动一个 Xvfb 实例,一个虚拟帧缓冲区
  • 使用 JsTestDriver:
    • 在虚拟帧缓冲区中启动一个 Firefox 实例(无头)
    • 捕获 Firefox 实例并运行测试套件
    • 生成符合 JUnit 的测试结果 .XML
  • 使用 Bamboo 检查结果文件以通过或失败构建

接下来我将介绍更详细的阶段.这就是我的目录结构最终的样子:

<上一页>库/JsTestDriver.jar测试/数量/equiv.jsQUnitAdapter.jsjsTestDriver.confrun_js_tests.sh测试.js测试报告/构建.xml

在构建服务器上:

  • 安装 Xvfb (apt-get install Xvfb)
  • 安装 Firefox (apt-get install firefox)

到您要构建的应用程序中:

  • 安装 JsTestDriver:http://code.google.com/p/js-测试驱动/
    • 添加 QUnit 适配器 equiv.jsQUnitAdapter.js
    • 配置 JsTestDriver (jsTestDriver.conf):
<上一页>服务器:http://localhost:4224加载:# 加载 QUnit 适配器(如果不使用 QUnit,可以省略)- qunit/equiv.js- qunit/QUnitAdapter.js# 测试自己(你会想要添加更多文件)- 测试.js

创建一个用于运行单元测试和生成测试结果的脚本文件(例如在 Bash 中,run_js_tests.sh):

#!/bin/bash# 写入输出 XML 的目录(如果不存在,则不会生成结果!)OUTPUT_DIR="../test-reports"mkdir $OUTPUT_DIRXVFB=`哪个 Xvfb`如果[$?"-eq 1];然后回显未找到 Xvfb."1号出口菲火狐=`哪个火狐`如果[$?"-eq 1];然后回声找不到火狐."1号出口菲$XVFB :99 -ac &# 将虚拟帧缓冲区启动到后台PID_XVFB="$!"# 获取进程IDexport DISPLAY=:99 # 设置显示使用 xvfb 的显示# 运行测试java -jar ../lib/JsTestDriver.jar --config jsTestDriver.conf --port 4224 --browser $FIREFOX --tests all --testOutput $OUTPUT_DIRkill $PID_XVFB # 关闭 xvfb (firefox 会被 JsTestDriver 彻底关闭)回声完成".

创建一个调用脚本的 Ant 目标:

最后,告诉 Bamboo 构建计划调用 test 目标并查找 JUnit 测试结果.这里默认的 "**/test-reports/*.xml" 就可以了.

I have a webapp build plan running on a Continuous Integration system (Atlassian Bamboo 2.5). I need to incorporate QUnit-based JavaScript unit tests into the build plan so that on each build, the Javascript tests would be run and Bamboo would interpret the test results.

Preferably I would like to be able to make the build process "standalone" so that no connections to external servers would be required. Good ideas on how to accomplish this? The CI system running the build process is on an Ubuntu Linux server.

解决方案

As I managed to come up with a solution myself, I thought it would be a good idea to share it. The approach might not be flawless, but it's the first one that seemed to work. Feel free to post improvements and suggestions.

What I did in a nutshell:

  • Launch an instance of Xvfb, a virtual framebuffer
  • Using JsTestDriver:
    • launch an instance of Firefox into the virtual framebuffer (headlessly)
    • capture the Firefox instance and run the test suite
    • generate JUnit-compliant test results .XML
  • Use Bamboo to inspect the results file to pass or fail the build

I will next go through the more detailed phases. This is what my my directory structure ended up looking like:

lib/
    JsTestDriver.jar
test/
    qunit/
            equiv.js
            QUnitAdapter.js
    jsTestDriver.conf
    run_js_tests.sh
    tests.js
test-reports/
build.xml

On the build server:

  • Install Xvfb (apt-get install Xvfb)
  • Install Firefox (apt-get install firefox)

Into your application to be built:

  • Install JsTestDriver: http://code.google.com/p/js-test-driver/
    • add the QUnit adapters equiv.js and QUnitAdapter.js
    • configure JsTestDriver (jsTestDriver.conf):

server: http://localhost:4224

load:
# Load QUnit adapters (may be omitted if QUnit is not used)
  - qunit/equiv.js
  - qunit/QUnitAdapter.js   

# Tests themselves (you'll want to add more files)
  - tests.js

Create a script file for running the unit tests and generating test results (example in Bash, run_js_tests.sh):

#!/bin/bash
# directory to write output XML (if this doesn't exist, the results will not be generated!)
OUTPUT_DIR="../test-reports"
mkdir $OUTPUT_DIR

XVFB=`which Xvfb`
if [ "$?" -eq 1 ];
then
    echo "Xvfb not found."
    exit 1
fi

FIREFOX=`which firefox`
if [ "$?" -eq 1 ];
then
    echo "Firefox not found."
    exit 1
fi

$XVFB :99 -ac &    # launch virtual framebuffer into the background
PID_XVFB="$!"      # take the process ID
export DISPLAY=:99 # set display to use that of the xvfb

# run the tests
java -jar ../lib/JsTestDriver.jar --config jsTestDriver.conf --port 4224 --browser $FIREFOX --tests all --testOutput $OUTPUT_DIR

kill $PID_XVFB     # shut down xvfb (firefox will shut down cleanly by JsTestDriver)
echo "Done."

Create an Ant target that calls the script:

<target name="test">        
    <exec executable="cmd" osfamily="windows">
        <!-- This might contain something different in a Windows environment -->
    </exec>

    <exec executable="/bin/bash" dir="test" osfamily="unix">
        <arg value="run_js_tests.sh" />
    </exec>
</target>   

Finally, tell the Bamboo build plan to both invoke the test target and look for JUnit test results. Here the default "**/test-reports/*.xml" will do fine.

相关文章