Asynchronous Testing

nzakas edited this page Nov 23, 2011 · 1 revision

YUI Test allows you to pause a currently running test and resume either after a set amount of time or at another designated time. The TestCase object has a method called wait(). When wait() is called, the test immediately exits (meaning that any code after that point will be ignored) and waits for a signal to resume the test.

A test may be resumed after a certain amount of time by passing in two arguments to wait(): a function to execute and the number of milliseconds to wait before executing the function (similar to using setTimeout()). The function passed in as the first argument will be executed as part of the current test (in the same scope) after the specified amount of time. For example:

var testCase = new YUITest.TestCase({

    name: "TestCase Name",
    
    //---------------------------------------------
    // Setup and tear down
    //---------------------------------------------
    
    setUp : function () {
        this.data = { name : "Nicholas", age : 29 };
    },

    tearDown : function () {
        delete this.data;
    },

    //---------------------------------------------
    // Tests
    //---------------------------------------------

    testAsync: function () {
        YUITest.Assert.areEqual("Nicholas", this.data.name, "Name should be 'Nicholas'");
        
        //wait 1000 milliseconds and then run this function
        this.wait(function(){
            YUITest.Assert.areEqual(29, this.data.age, "Age should be 29");
        
        }, 1000);   
    }  
});

In this code, the testAsync() function does one assertion, then waits 1000 milliseconds before performing another assertion. The function passed into wait() is still in the scope of the original test, so it has access to this.data just as the original part of the test does. Timed waits are helpful in situations when there are no events to indicate when the test should resume.

If you want a test to wait until a specific event occurs before resuming, the wait() method can be called with a timeout argument (the number of milliseconds to wait before considering the test a failure). At that point, testing will resume only when the resume() method is called. The resume() method accepts a single argument, which is a function to run when the test resumes. This function should specify additional assertions. If resume() isn't called before the timeout expires, then the test fails. The following tests to see if the Anim object has performed its animation completely:

var testCase = new YUITest.TestCase({

    name: "TestCase Name",
    
    //---------------------------------------------
    // Tests
    //---------------------------------------------

    testAnimation : function (){
        
        //animate width to 400px
        var myAnim = new Y.Anim({
            node: '#testDiv', 
            to: { 
                width: 400
            },
            duration: 3
        });
        
        var test = this; 
        
        //assign oncomplete handler
        myAnim.on("end", function(){
        
            //tell the TestRunner to resume
            test.resume(function(){
            
                YUITest.Assert.areEqual(myAnim.get("node").get("offsetWidth"), 400, "Width of the DIV should be 400.");
            
            });
        
        });

        //start the animation
        myAnim.run();
        
        //wait until something happens
        this.wait(3100);
    
    }  
});

In this example, an Anim object is used to animate the width of an element to 400 pixels. When the animation is complete, the end event is fired, so that is where the resume() method is called. The function passed into resume() simply tests that the final width of the element is indeed 400 pixels. Once the event handler is set up, the animation begins.

In order to allow enough time for the animation to complete, the wait() method is called with a timeout of 3.1 seconds (just longer than the 3 seconds needed to complete the animation). At that point, testing stops until the animation completes and resume() is called or until 3100 milliseconds have passed.