web-dev-qa-db-ja.com

JavaScriptによる自動ユニットテスト

自動ビルドプロセスにJavaScriptユニットテストを組み込んでいます。現在、JSUnitはJUnitで適切に動作しますが、それは放棄されているようで、AJAX、デバッグ、およびタイムアウトのサポートが不足しています。

YUIテスト、JQueryのQUnit、jQUnit( http://code.google.com/p/jqunit/ )などの単体テストライブラリを(ANTで)自動化する運があった人はいますか?

注:カスタムビルドAJAXライブラリを使用しているため、DojoのDOHの問題は、独自のAJAX関数呼び出しとイベントハンドラーを使用する必要があることです。 AJAX単体テストで動作します。

60
Chris MacDonald

多くのJavaScriptユニットテストフレームワーク(jsUnit、scriptaculousなど)がありますが、自動ビルドで使用できるのはjsUnitだけです。

「真の」ユニットテストを実行している場合、AJAXサポートは必要ありません。たとえば、DWRなどのRPC ajaxフレームワークを使用している場合は、簡単にモック関数を作成できます。

 function mockFunction(someArg、callback){
 var result = ...; //いくつかの処理
 setTimeout(
function(){callback(result); }、 300 //偽のレイテンシ
); }

そして、はい、JsUnitはタイムアウトを処理します: jsUnitテストでのシミュレーション時間

20

私は今取り組んでいる新しいプロジェクトでJavascript TDDを始めようとしています。私の現在の計画は、ユニットテストを行うために qunit を使用することです。開発中は、ブラウザでテストページを更新するだけでテストを実行できます。

継続的インテグレーション(およびすべてのブラウザーでテストが実行されるようにする)の場合、 Selenium を使用して、各ブラウザーでテストハーネスを自動的に読み込み、結果を読み取ります。これらのテストは、ソース管理へのチェックインごとに実行されます。

また、テストのコードカバレッジ分析を取得するために JSCoverage を使用します。これもSeleniumで自動化されます。

私は現在これをセットアップしている最中です。セットアップが完了したら、この回答をより正確な詳細で更新します。


テストツール:

24
Karl

js-test-driver の大ファンです

CI環境で適切に動作し、クロスブラウザーテストのために実際のブラウザーをキャプチャできます。

13
groodt

私は最近、JsUnitを使用してその上にJsMockフレームワークを作成するBrunoによる記事を読みました...非常に興味深いです。彼の作品を使ってJavascriptコードのユニットテストを開始しようと考えています。

JavaScriptのモックまたはブラウザ環境外でJavaScriptを単体テストする方法

4
Elijah Manor

私は Hudson CIを実行してJasmineBDDを実行する (ヘッドレス)、少なくとも純粋なjavascriptユニットテスト用です。

(Hudson実行Javaシェル経由、Envjs実行、JasmineBDD実行)

プロトタイプのように、大きなライブラリでニースをプレイすることはまだできていません。

4
Ingvald

調べてください YUITest

2
Hank Gay

私はjsunitが一種のVineで死にかけていることに同意しています。 YUIテストに置き換えました。

QUnitを使用した例と同様に、Seleniumを使用してテストを実行しています。このテストは、通常のUI回帰テストのような依存関係がないために(他のSeleniumテストとは独立して)実行しています(たとえば、サーバーへのアプリのデプロイ)。

最初に、すべてのテストhtmlファイルに含まれている基本のJavaScriptファイルがあります。これは、YUIインスタンス、テストランナー、YUI.Test.Suiteオブジェクト、およびTest.Caseの設定を処理します。これには、Seleniumを介してアクセスしてテストスイートを実行し、テストランナーがまだ実行されているかどうかを確認し(実行が完了するまで結果は利用できません)、テスト結果を取得する(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に関しては、パラメーター化されたテストを使用しました。テストをIEとデータメソッドのFireFoxの両方で実行し、テスト結果をブラウザ配列、テストファイル名、テスト名を含むオブジェクト配列のリストに解析します。結果(合格、失敗、または無視)とメッセージ。

実際のテストは、テスト結果を表明するだけです。 「合格」と等しくない場合、テストは失敗し、YUIテスト結果から返されるメッセージが表示されます。

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

これがお役に立てば幸いです。

2
Josh

私はあなたの質問日を見て、当時はいくつかの良いJSテストlib/frameworkがありました。今日では、TDD、BDD、Assetion、ランナーサポートの有無にかかわらず、さらに多くの異なる焦点を見つけることができます。

このゲームには、Mocha、Chai、QUnit、Jasmineなどの多くのプレイヤーがいます... JS /モバイル/ Webテストに関する詳細情報は this ブログにあります...

1
lastboy

Java環境(antのような)環境で qunit テストを実行できる新しいプロジェクトがあるため、クライアント側のテストスイートを他のユニットテストと完全に統合できます。

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

私はそれをjQueryプラグインのユニットテストに使用しました objx コード、カスタムOO JavaScript、そしてそれは変更なしですべてに対して機能します。

1
Mat Ryer

ブラウザーを使用せずにブラウザー依存のJavaScriptテストを検証するための little library を公開しました。これは、zombie.jsを使用してテストページをロードし、結果を検査するnode.jsモジュールです。私はそれについて書きました 私のブログで 。自動化は次のようになります。

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

});
1
liammclennan

私が取り組んでいるプロジェクトでは、 Js-Test-Driver hosting Jasmine on Chrome 10 with Jasmine-JSTD-Adapter JS-Test-Driverに含まれる Code Coverage テストの利用を含む。毎回いくつかの問題がありますが、 CI環境でブラウザを変更または更新する ジャスミンテストは非同期テストの軽微な問題でかなりスムーズに実行されていますが、私が知っている限り、これらはジャスミンクロックを使用して回避できます。まだパッチを当てる機会がありませんでした。

1
Steven de Salas

Antで実行できる別のJSテストフレームワークは CrossCheck です。プロジェクトのビルドファイルにAntを介してCrossCheckを実行する例があります。

CrossCheckは、限られた成功を収めて、XMLHttpRequestおよびタイムアウト/間隔のモックスタイル実装を含むブラウザをエミュレートしようとします。

ただし、現在、WebページからのJavaScriptのロードは処理していません。ロードしてテストするJavaScriptファイルを指定する必要があります。すべてのJSをHTMLから切り離しておくと、うまくいく場合があります。

0
Jason Wadsworth

これは、いくつかのテストツールの優れた評価です。

TDD用のJavaScriptユニットテストツール

私は個人的に好み https://code.google.com/p/js-test-driver/

0
Alexvx

私は、Antビルドプロセス内でQUnit htmlテストファイルを実行するために、ヘッドレスWebkitブラウザである Phantom JS を使用するAntタスクを作成しました。また、いずれかのテストが失敗すると、ビルドも失敗する可能性があります。

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

0
Phil Mander