我正在尝试将一些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也将自动执行此操作。
我目前正在进行此设置。一旦设置完成,我将使用更准确的详细信息更新此答案。
测试工具:
有很多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分开,则可能对您有用。