Firebug Automated Test Examples

From FirebugWiki

Revision as of 09:58, 4 March 2010 by Honza (Talk | contribs)
Jump to: navigation, search

See some examples demonstrating how an automated Firebug test can be developed. All examples are part of Firebug test suite.


Every test is usually composed from following parts (see Running Automated Test Suite#Terminology), but depends on the nature of the test. Only the Test Driver is necessary for automation.

  • Test Page (*.html; *.php) - The test page with instruction so the test can be also executed manually.
  • Test Driver (*.js) - The test driver code that automates the test and verify results.


Test file templates:


All APIs used by a test driver are defined within FBTest namespace.


Contents

Example: Basic Test

This test is intended to show basic construct of an automated test. This test doesn't have a test page and implements only a test driver part.

See full test source code here.

exampleNet1.html

function runTest()
{
    // A message displayed within Firebug tracing console.
    FBTest.sysout("exampleTest.START");

    // A message displayed under the test within Firebug test console.
    FBTest.progress("This is a progress message");

    // Verification
    FBTest.ok(true, "This is a positive verification");
    FBTest.ok(false, "This is a negative verification");

    // Verification
    FBTest.compare("Expected", "Expected", "Compare test (positive)");
    FBTest.compare("Expected", "Actual", "Compare test (negative)");

    FBTest.testDone("exampleTest.DONE");
}


A few notes:

  • runTest is the test entry point. It's automatically called by Firebug test harness framework). This is where the test starts and it must be part of every test.


Example: Network request in the Net panel

This test is intended to verify that a network request is properly displayed in the Net panel. The test is composed from three files:

  • exampleNet1.html (test page)
  • exampleNet1.php (Firebug is using PHP for dynamic server parts)
  • exampleNet1.js (test driver)

See full test source code here.


exampleNet1.html

<button id="testButton" onclick="onExecuteTest()">Execute Test</button>
<script type="text/javascript">
function onExecuteTest()
{
    var request = new XMLHttpRequest();
    request.open("GET", "exampleNet1.php", true);
    request.send(null);
}
</script>

The only goal here is to execute a XHR, which is done if the user (or our test-driver later) clicks the Execute Test button.


exampleNet1.php

<?php 
header("Content-Type: text/plain");
echo "Simple response";
?>


Finally, the most important part is the test-driver that automates the execution.

exampleNet1.js

function runTest()
{
    FBTest.sysout("exampleNet1.START");

    // 1) Load test case page
    FBTest.openNewTab(basePath + "examples/exampleNet1.html", function(win)
    {
        // 2) Open Firebug and enable the Net panel.
        FBTest.openFirebug();
        FBTest.enableNetPanel(function(win)
        {
            // 3) Select Net panel
            var panel = FW.FirebugChrome.selectPanel("net");

            // Asynchronously wait for the request beeing displayed.
            onRequestDisplayed(function(netRow)
            {
                // TODO: test code, verify UI, etc.

                // 5) Finish test
                FBTest.testDone("exampleNet1.DONE");
            });

            // 4) Execute test by clicking on the 'Execute Test' button.
            FBTest.click(win.document.getElementById("testButton"));
        });
    });
}

function onRequestDisplayed(callback)
{
    // Create listener for mutation events.
    var doc = FBTest.getPanelDocument();
    var recognizer = new MutationRecognizer(doc.defaultView, "tr",
        {"class": "netRow category-xhr loaded"});

    // Wait for a XHR log to appear in the Net panel.
    recognizer.onRecognizeAsync(callback);
}


A few notes:

  • FBTest.getHTTPURLBase() returns base directory with all tests. All files of this test are stored within examples subdirectory.
  • FBTest.openNewTab opens new tab asynchronously. This is why, the other steps are executed within a handler passed into this function.
  • FBTest.enableNetPanel is also asynchronous and it also reloads the page (this inline with the Activation model)
  • onRequestDisplayed this function uses MutationRecognizer listener that fires when a TR element with netRow category-xhr loaded classes is created.



Example: Break in debugger

This test is intended to verify that Firebug properly break in debugger. This test is composed from two files:

  • exampleScript1.html (test page)
  • exampleScript1.js (test driver)

See full source code here.


exampleScript1.html

<button id="testButton" onclick="onExecuteTest()">Execute Test</button>
<script type="text/javascript">
function onExecuteTest()
{
    debugger;
}
</script>


exampleScript1.js

function runTest()
{
    FBTest.sysout("exampleScript1.START");

    // 1) Load test case page
    FBTest.openNewTab(basePath + "examples/exampleScript1.html", function(win)
    {
        // 2) Open Firebug and enable the Script panel.
        FBTest.openFirebug();
        FBTest.enableScriptPanel(function(win)
        {
            // 3) Select the Script panel
            var panel = FW.FirebugChrome.selectPanel("script");

            // Asynchronously wait for break in debugger.
            var chrome = FW.Firebug.chrome;
            FBTest.waitForBreakInDebugger(chrome, 21, false, function(row)
            {
                // TODO: test code, verify UI, etc.

                // Resume debugger.
                FBTest.clickContinueButton();

                // 5) Finish test.
                FBTest.testDone("exampleScript1.DONE");
            });

            // 4) Execute test by clicking on the 'Execute Test' button.
            FBTest.click(win.document.getElementById("testButton"));
        });
    });
}


A few notes:

  • The overall structure (loading the test page, opening Firebug, selecting Script panel) is pretty much the same as in the first test for the Net panel.
  • FBTest.waitForBreakInDebugger() waits till the script execution halts in the debugger.
  • FBTest.clickContinueButton() clicks on the Resume button to resume debugger's state.
  • Additional code that verifies some other aspects of the Firebug state can be within the callback.


FBTest.waitForBreakInDebugger(chrome, lineNo, breakpoint, callback)
chrome Current Firebug's chrome object.
lineNo Expected source line number where the break should happen.
breakpoint Set to true if the break should happen on a breakpoint.
callback Handler that is called when break happens.


Example: Firebug Library API Test

This example is intended to show how to create a test for a library functions. In this example only a test driver is implemented.

See full source code here.

exampleLib1.js

function runTest()
{
    FBTest.sysout("exampleLib1.START");

    var element = document.createElement("div");
    element.appendChild(document.createTextNode("some text"));

    var html = FW.FBL.getElementHTML(element);
    FBTest.compare("<div>some text</div>", html, "Verify FW.FBL.getElementHTML()");

    FBTest.testDone("exampleScript1.DONE");
}
  • The test driver code runs within it's own iframe so, document is fully available.
  • The suspect function is 'getElementHTML' in this case.


Example: Console object API

This test is intended to verify console.log method by checking the output in the Console panel. The test is composed from two files:

  • exampleConsoleAPI1.html (test page)
  • exampleConsoleAPI1.js (test driver)

See full test source code here.


exampleConsoleAPI1.html

<button id="testButton" onclick="onExecuteTest()">Execute Test</button>
<script type="text/javascript">
function onExecuteTest()
{
    // Usage of the console object
    console.log("Hello World!");
}
</script>

The only goal here is to use the console object, which is done if the user (or our test-driver code) clicks the Execute Test button.


exampleConsoleAPI1.js

function runTest()
{
    FBTest.sysout("console.API.START");
    FBTest.openNewTab(basePath + "examples/exampleConsoleAPI1.html", function(win)
    {
        FBTest.openFirebug();
        FBTest.enableConsolePanel(function(win)
        {
            var config = {tagName: "div", classes: "logRow logRow-log"};
            FBTest.waitForDisplayedElement("console", config, function(row)
            {
                FBTest.compare("Hello World!", row.textContent,
                    "The proper message must be displayed.");
                FBTest.testDone("console.dir.DONE");
            });

            // Execute test implemented on the test page.
            FBTest.click(win.document.getElementById("testButton"));
        });
    });
}


A few notes:

  • FBTest.enableConsolePanel() This method enables the Console panel, reloads the page and as soon as the page is loaded it executes the callback function.
  • FBTest.waitForDisplayedElement Waits till a div element with classes logRow and logRow-log is created within the Console panel. The proper element is passed into the callback function as row parameter.



Example: Asynchronous tasks within a test

This example shows how to create a test that is composed from a set of asynchronous tasks. The test is implemented as test-driver only:

  • exampleTaskList1.js (test driver)

See full test source code here.

function runTest()
{
    FBTest.sysout("examples.tasklist.START");

    var tasks = new FBTest.TaskList();
    tasks.push(function(callback) {
        FBTest.progress("Task 1 executed");

        setTimeout(function()
        {
            // TODO: test implementation (after an async operation)
            // Continue with other tests.
            callback();
        }, 100);
    });

    tasks.run(function() {
        FBTest.testDone("examples.tasklist.DONE");
    });
}


A few notes:

  • new FBTest.TaskList() Create instance of a task list.
  • tasks.push This way any number of tasks (functions) can be appended into the list. There is a callback parameter passed into every task so, the task can finish itself by executing it.
  • tasks.run Runs all appended tasks in the order. Passed callback is called when all tasks finishes the execution.


Personal tools