关于jquery:使用JavaScript进行自动单元测试

关于jquery:使用JavaScript进行自动单元测试

Automated Unit Testing with JavaScript

我正在尝试将一些JavaScript单元测试合并到我的自动构建过程中。 当前,JSUnit与JUnit可以很好地协作,但是它似乎已经被弃用,并且缺乏对AJAX,调试和超时的良好支持。

有没有人有运气(使用ANT)自动化单元测试库,例如YUI测试,JQuery的QUnit或jQUnit(http://code.google.com/p/jqunit/)?

注意:我使用定制的AJAX库,所以Dojo的DOH的问题在于它要求您使用自己的AJAX函数调用和事件处理程序来进行任何AJAX单元测试。


我即将开始在我正在从事的新项目中执行Javascript TDD。我当前的计划是使用qunit进行单元测试。在开发测试时,只需在浏览器中刷新测试页面即可运行测试。

为了进行持续集成(并确保测试在所有浏览器中运行),我将使用Selenium在每个浏览器中自动加载测试工具,并读取结果。这些测试将在每次签入源控制时运行。

我还将使用JSCoverage进行测试的代码覆盖率分析。 Selenium也将自动执行此操作。

我目前正在进行此设置。一旦设置完成,我将使用更准确的详细信息更新此答案。

测试工具:

  • qunit
  • JSCoverage

有很多javascript单元测试框架(jsUnit,scriptaculous等),但是jsUnit是我所知道的唯一可以与自动构建一起使用的框架。

如果您要进行"真实"的单元测试,则不需要AJAX支持。例如,如果您使用的是诸如DWR之类的RPC ajax框架,则可以轻松编写一个模拟函数:

1
2
3
4
5
6
7
   function mockFunction(someArg, callback) {
      var result = ...; // some treatments  
      setTimeout(
        function() { callback(result); },
        300  // some fake latency
      );
    }

是的,JsUnit可以处理超时:在jsUnit测试中模拟时间


我是js-test-driver的忠实拥护者

它在CI环境中运行良好,并且能够捕获实际的浏览器以进行跨浏览器测试。


我只是让Hudson CI运行JasmineBDD(无头),至少用于纯JavaScript单元测试。

(Hudson通过外壳运行Java,运行Envjs,运行JasmineBDD。)

不过,我还没有像大型原型库那样在大型图书馆中表现出色。


最近,我读了Bruno的文章,该文章使用JsUnit并在此之上创建了一个JsMock框架...非常有趣。我正在考虑使用他的工作来开始对Javascript代码进行单元测试。

模拟JavaScript或如何在浏览器环境之外进行单元测试Java


我同意jsunit快死了。我们刚刚完成了将其替换为YUI测试。

与使用qUnit的示例相似,我们使用Selenium运行测试。我们独立于其他硒测试而独立运行此测试,只是因为它不具有普通UI回归测试所具有的依赖性(例如,将应用程序部署到服务器)。

首先,我们在所有测试html文件中都包含一个基本的javascript文件。这负责设置YUI实例,测试运行器,YUI.Test.Suite对象以及Test.Case。它具有可以通过Selenium访问的方法来运行测试套件,检查测试运行程序是否仍在运行(结果在完成后才可用),并获取测试结果(我们选择了JSON格式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
var yui_instance; //the YUI instance
var runner;  //The YAHOO.Test.Runner
var Assert; //an instance of YAHOO.Test.Assert to save coding
var testSuite; //The YAHOO.Test.Suite that will get run.

/**
 * Sets the required value for the name property on the given template, creates
 * and returns a new YUI Test.Case object.
 *
 * @param template the template object containing all of the tests
 */

function setupTestCase(template) {
    template.name ="jsTestCase";
    var test_case = new yui_instance.Test.Case(template);
    return test_case;
}

/**
 * Sets up the test suite with a single test case using the given
 * template.
 *
 * @param template the template object containing all of the tests
 */

function setupTestSuite(template) {
    var test_case = setupTestCase(template);
    testSuite = new yui_instance.Test.Suite("Bond JS Test Suite");
    testSuite.add(test_case);
}

/**
 * Runs the YAHOO.Test.Suite
 */

function runTestSuite() {
    runner = yui_instance.Test.Runner;
    Assert = yui_instance.Assert;

    runner.clear();
    runner.add(testSuite);
    runner.run();
}

/**
 * Used to see if the YAHOO.Test.Runner is still running.  The
 * test results are not available until it is done running.
 */

function isRunning() {
    return runner.isRunning();
}

/**
 * Gets the results from the YAHOO.Test.Runner
 */

function getTestResults() {
    return runner.getResults(yui_instance.Test.Format.JSON);
}

至于硒方面,我们使用了参数化测试。我们使用数据方法在IE和FireFox中运行测试,将测试结果解析为Object数组列表,每个数组包含浏览器名称,测试文件名称,测试名称,结果(通过,失败或忽略)和消息。

实际测试只是断言测试结果。如果不等于"通过",则它将通过YUI测试结果返回的消息使测试失败。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
    @Parameters
public static List<Object[]> data() throws Exception {
    yui_test_codebase ="file:///c://myapppath/yui/tests";

    List<Object[]> testResults = new ArrayList<Object[]>();

    pageNames = new ArrayList<String>();
    pageNames.add("yuiTest1.html");
    pageNames.add("yuiTest2.html");

    testResults.addAll(runJSTestsInBrowser(IE_NOPROXY));
    testResults.addAll(runJSTestsInBrowser(FIREFOX));
    return testResults;
}

/**
 * Creates a selenium instance for the given browser, and runs each
 * YUI Test page.
 *
 * @param aBrowser
 * @return
 */

private static List<Object[]> runJSTestsInBrowser(Browser aBrowser) {
    String yui_test_codebase ="file:///c://myapppath/yui/tests/";
    String browser_bot ="this.browserbot.getCurrentWindow()"
    List<Object[]> testResults = new ArrayList<Object[]>();
    selenium = new DefaultSelenium(APPLICATION_SERVER, REMOTE_CONTROL_PORT, aBrowser.getCommand(), yui_test_codebase);
    try {
        selenium.start();

        /*
         * Run the test here
         */

        for (String page_name : pageNames) {
            selenium.open(yui_test_codebase + page_name);
            //Wait for the YAHOO instance to be available
            selenium.waitForCondition(browser_bot +".yui_instance != undefined","10000");
            selenium.getEval("dom=runYUITestSuite(" + browser_bot +")");

            //Output from the tests is not available until
            //the YAHOO.Test.Runner is done running the suite
            selenium.waitForCondition("!" + browser_bot +".isRunning()","10000");
            String output = selenium.getEval("dom=getYUITestResults(" + browser_bot +")");

            JSONObject results = JSONObject.fromObject(output);
            JSONObject test_case = results.getJSONObject("jsTestCase");
            JSONArray testCasePropertyNames = test_case.names();
            Iterator itr = testCasePropertyNames.iterator();

            /*
             * From the output, build an array with the following:
             *  Test file
             *  Test name
             *  status (result)
             *  message
             */

            while(itr.hasNext()) {
                String name = (String)itr.next();
                if(name.startsWith("test")) {
                    JSONObject testResult = test_case.getJSONObject(name);
                    String test_name = testResult.getString("name");
                    String test_result = testResult.getString("result");
                    String test_message = testResult.getString("message");
                    Object[] testResultObject = {aBrowser.getCommand(), page_name, test_name, test_result, test_message};
                    testResults.add(testResultObject);
                }
            }

        }
    } finally {
        //if an exception is thrown, this will guarantee that the selenium instance
        //is shut down properly
        selenium.stop();
        selenium = null;
    }
    return testResults;
}
/**
 * Inspects each test result and fails if the testResult was not"pass"
 */

@Test
public void inspectTestResults() {
    if(!this.testResult.equalsIgnoreCase("pass")) {
        fail(String.format(MESSAGE_FORMAT, this.browser, this.pageName, this.testName, this.message));
    }
}

我希望这是有帮助的。


看看YUITest


我查看了您的问题日期,然后发现有一些不错的JS测试lib / framework。
今天,您可以找到更多的内容,并且关注的重点不同,例如TDD,BDD,Assetion,以及是否有跑步者支持。

此游戏中有很多玩家,例如摩卡,柴,QUnit,茉莉花等。
您可以在此博客中找到有关JS / Mobile / web测试的更多信息...


我已经发布了一个小库,无需使用浏览器即可验证与浏览器相关的JavaScript测试。这是一个使用zombie.js加载测试页并检查结果的node.js模块。我已经在我的博客上写过。这是自动化的样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var browsertest = require('../browsertest.js').browsertest;

describe('browser tests', function () {

it('should properly report the result of a mocha test page', function (done) {
    browsertest({
        url:"file:///home/liam/work/browser-js-testing/tests.html",
        callback: function() {
            done();
        }
    });
});

});

我正在研究的项目使用带有Jasmine-JSTD-Adapter的Chrome 10上的Jasmine托管Js-Test-Driver,包括利用JS-Test-Driver中包含的Code Coverage测试。尽管每次我们在CI环境中更改或更新浏览器时都会遇到一些问题,但是茉莉花测试运行相当顺利,而异步测试只有很小的问题,但是据我所知,使用茉莉花时钟可以解决这些问题,但是我还没有还没有机会修补它们。


有一个新项目,可让您在Java环境(如ant)中运行qunit测试,以便将客户端测试套件与其他单元测试完全集成。

http://qunit-test-runner.googlecode.com

我已使用它对jQuery插件,objx代码,自定义OO JavaScript进行单元测试,并且无需修改即可用于所有内容。


这是对几种测试工具的良好评价。

TDD的JavaScript单元测试工具

我个人更喜欢
https://code.google.com/p/js-test-driver/


我编写了一个Ant任务,该任务使用无头Webkit浏览器Phantom JS在Ant构建过程中运行QUnit html测试文件。如果任何测试失败,它也会使构建失败。

https://github.com/philmander/ant-jstestrunner


可以与Ant一起运行的另一个JS测试框架是CrossCheck。在项目的构建文件中有一个通过Ant运行CrossCheck的示例。

CrossCheck尝试模拟浏览器,但收效甚微,其中包括XMLHttpRequest和超时/间隔的模拟样式实现。

但是,它目前无法处理从网页加载javascript。您必须指定要加载和测试的javascript文件。如果您将所有JS与HTML分开,则可能对您有用。


推荐阅读

    linux下进程调试命令?

    linux下进程调试命令?,系统,工作,软件,信息,命令,基础,地址,状态,进程,实时,L

    linux合并行命令行?

    linux合并行命令行?,工作,系统,地址,信息,文件,代码,目录,命令,功能,内容,Lin

    linux网口调试命令?

    linux网口调试命令?,系统,工作,地址,信息,网络,技术指标,状态,电脑,命令,网

    linux命令合并重复行?

    linux命令合并重复行?,地址,文件,系统,命令,代码,工作,基础,内容,两个,控制

    linux合并命令怎么用?

    linux合并命令怎么用?,地址,文件,位置,工作,电脑,代码,系统,命令,文档,内容,L

    linux命令行调试代码?

    linux命令行调试代码?,环境,代码,信息,平台,程序,编辑,版本,步骤,体系结构,

    linux下单步调试命令?

    linux下单步调试命令?,信息,系统,代码,工程,地址,工具,工作,数据,管理,环境,l

    linux串口调试命令?

    linux串口调试命令?,设备,数据,信息,数字,系统,标准,通讯,软件,通用,状态,lin

    linux合并保存命令行?

    linux合并保存命令行?,文件,地址,代码,工作,命令,两个,内容,目录,方法,文件

    linux文件夹合并命令?

    linux文件夹合并命令?,文件,对比,第一,下来,命令,文件夹,两个,字段,内容,数

    使用linux命令合并?

    使用linux命令合并?,文件,代码,工作,命令,内容,两个,目录,方法,麻烦事,发现,l

    linux分区合并命令行?

    linux分区合并命令行?,系统,管理,地址,电脑,名字,工具,数据,工作,分区,地方,

    linux调试终端命令?

    linux调试终端命令?,系统,工作,地址,首页,电脑,终端,命令,标准,信息,基础,求L

    合并文件的linux命令?

    合并文件的linux命令?,文件,代码,位置,系统,命令,内容,两个,文件夹,链接,方

    linux脚本调试的命令?

    linux脚本调试的命令?,工作,系统,管理,命令,地址,标准,脚本,底部,代码,官网,l

    linux命令调试模式?

    linux命令调试模式?,系统,工作,信息,地址,工程,命令,工具,环境,设备,地方,lin

    linux调试驱动的命令?

    linux调试驱动的命令?,系统,网络,官网,百度,地址,下来,第一,官方网站,软件,

    linux命令调试过程?

    linux命令调试过程?,代码,通用,地方,信息,系统,程序,进程,命令,编辑,断点,如

    linux合并命令是什么?

    linux合并命令是什么?,文件,代码,位置,系统,命令,两个,内容,文件夹,链接,功