使用JavaScript进行自动unit testing

我正在尝试将一些JavaScriptunit testing集成到我的自动构build过程中。 目前JSUnit与JUnit很好地协作,但似乎是放弃了,并且对AJAX,debugging和超时缺乏良好的支持。

有没有人有运气自动化(与ANT)unit testing库,如YUItesting,JQuery的QUnit,或jQUnit( http://code.google.com/p/jqunit/ )?

注意:我使用了一个定制的AJAX库,所以Dojo的DOH的问题是它需要你使用自己的AJAX函数调用和事件处理程序来处理任何AJAXunit testing。

在那里有很多的javascriptunit testing框架(jsUnit,scriptaculous,…),但是jsUnit是我所知道的唯一可以用于自动构build的。

如果你正在做“真正的”unit testing,你不应该需要AJAX支持。 例如,如果您使用的是诸如DWR之类的RPC ajax框架,则可以轻松编写一个模拟函数:

   函数mockFunction(someArg,callback){
       var result = ...;  //一些治疗   
      的setTimeout( 
function(){callback(result); }, 300 / /一些虚假的延迟
); }

是的,JsUnit处理超时: 在jsUnittesting中模拟时间

我正要开始在我正在开发的一个新项目上开发Javascript TDD。 我目前的计划是用qunit来做unit testing。 开发testing可以通过在浏览器中刷新testing页面来运行。

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

我也将使用JSCoverage来获得testing的代码覆盖分析。 Selenium也会自动执行此操作。

我目前正在设置这个中间。 一旦我完成设置,我会更新这个答案。


testing工具:

  • qunit
  • JSCoverage
  • selenium

我是js-test-driver的忠实粉丝

它在CI环境下运行良好,能够捕获实际的浏览器进行跨浏览器testing。

我最近阅读了Bruno使用JsUnit的一篇文章,并在其上创build了一个JsMock框架…非常有趣。 我正在考虑使用他的工作开始unit testing我的Javascript代码。

模拟Javascript或如何在浏览器环境外unit testingJavascript

我刚刚得到Hudson CI运行JasmineBDD (无头),至less对于纯JavaScriptunit testing。

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

尽pipe如此,我还没有和一个大型图书馆打好关系。

看着YUITest

我同意jsunit在藤上死去。 我们刚刚用YUI Testreplace它。

与使用qUnit的示例类似,我们使用Selenium运行testing。 我们正在独立于其他seleniumtesting运行此testing,因为它没有正常的UI回归testing所具有的依赖性(例如将应用程序部署到服务器)。

首先,我们有一个基本的JavaScript文件,包含在我们所有的testinghtml文件中。 这将处理设置YUI实例,testing运行器,YUI.Test.Suite对象以及Test.Case。 它有一个可以通过Selenium访问的方法来运行testing套件,检查testing运行器是否仍在运行(结果在完成之后才可用),并获取testing结果(我们select了JSON格式)

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); } 

至于selenium的东西,我们使用了参数化testing。 我们在数据方法中在IE和FireFox中运行我们的testing,将testing结果parsing成对象数组列表,每个数组包含浏览器名称,testing文件名称,testing名称,结果(通过,失败或忽略)和消息。

实际testing只是声明testing结果。 如果不等于“通过”,则YUItesting结果返回的消息将失败。

  @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)); } } 

我希望这是有帮助的。

有一个新的项目可以让你在Java环境(如ant)中运行qunittesting,这样你就可以将你的客户端testing套件与其他unit testing完全集成。

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

我用它来unit testingjQuery插件, objx代码,自定义的OO JavaScript,它可以在没有修改的情况下工作。

我正在使用的项目使用Js-Test-Driver托pipeJasmine -JSTD-Adapter上的Jasmine,包括使用JS-Test-Driver中包含的代码覆盖率testing。 虽然每次我们在CI环境中更改或更新浏览器时都会遇到一些问题,但是茉莉花testing运行起来相当顺利,只有一些小小的问题,但是据我所知,这些可以用Jasmine Clock解决,但是我没有没有机会修补它们。

我已经发布了一个小库来validation依赖于浏览器的JavaScripttesting,而不必使用浏览器。 它是一个node.js模块,它使用zombie.js加载testing页面并检查结果。 我在我的博客上写过 这是自动化的样子:

 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(); } }); }); }); 

我看了你的问题date,然后有几个很好的JStestinglib /框架。 今天,你可以find更多和不同的焦点,如TDD,BDD,评估和有/没有亚军的支持。

在这个游戏中有很多玩家喜欢摩卡,柴,QUnit,茉莉花等…你可以find更多的信息在这个博客关于JS /手机/networkingtesting…

另一个可以用Ant运行的JStesting框架是CrossCheck 。 有一个在项目的构build文件中通过Ant运行CrossCheck的例子。

CrossCheck的尝试只是有限的成功,模拟一个浏览器,包括XMLHttpRequest的模拟式实现和超时/间隔。

但是,它目前不处理从网页加载JavaScript。 你必须指定你想加载和testing的JavaScript文件。 如果你把所有的JS与你的HTML分开,它可能适用于你。

我写了一个Ant任务,使用Phantom JS (一个无头的webkit浏览器)在Ant构build过程中运行QUnit htmltesting文件。 如果任何testing失败,它也可能会失败。

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

这是对几个testing工具的一个很好的评估。

用于TDD的JavaScriptunit testing工具

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