Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of conditional statements in Jasmine tests

I have two functions I want to test; one that runs only in "modern browsers" the other that runs only in "older" browsers.

I am using Jasmine as my testing framework and Karma to run my tests. Karma will launch many browsers in which all the tests are run.

My problem is that testing ALL my functions in ALL browsers will lead some tests to fail. For example, testing a function that should run only in modern browsers will fail in when tested in IE8.

Code to test:

function getStuffFromSmartBrowser() {
    return 'foo';
}

function getStuffFromNotSoSmartBrowser() {
    return 'bar';
}

if ('intelligence' in browser) {
    getStuffFromSmartBrowser();
} else {
    getStuffFromNotSoSmartBrowser();
}

Original test code:

describe("A suite", function () {
    it("for smart browsers", function () {
        expect(getStuffFromSmartBrowser()).toEqual('foo');
    });
});

describe("A suite", function () {
    it("for not so smart browsers", function () {
        expect(getStuffFromNotSoSmartBrowser()).toEqual('bar');
    });
});

In these test cases, one test will fail in one type of browsers while the other test will fail in the other type of browsers.

Alternative test code:

describe("A suite", function () {
    if ('intelligence' in browser) {
        it("for smart browsers", function () {
            expect(getStuffFromSmartBrowser()).toEqual('foo');
        });
    } else {
        it("for not so smart browsers", function () {
            expect(getStuffFromNotSoSmartBrowser()).toEqual('bar');
        });
    }
});

The alternative test code run perfectly well in all tested browsers.

Questions:

A - Is it good practice to use conditional statements in tests?

B - If not, what would be a better approach?

like image 943
redrum Avatar asked Mar 21 '14 21:03

redrum


People also ask

What is Jasmine used for in testing?

Jasmine is a very popular JavaScript behavior-driven development (In BDD, you write tests before writing actual code) framework for unit testing JavaScript applications. It provides utilities that can be used to run automated tests for both synchronous and asynchronous code.

Which hook you use to setup a test in Jasmine?

Jasmine offers the beforeEach and afterEach hooks. A hook is a function that you can place inside a describe block to add custom programming. In the case of a beforeEach hook, the program will execute this logic before running the defined test cases that the describe block holds.


1 Answers

It's generally considered bad practice to have conditionals inside the test code. Outside of the test code is slightly more acceptable and, in the absence of a built-in mechanism to select test specs by browser, your solution is probably the simplest. However, you are coupling your unit tests to the browser-specific implementations.

A "better" approach would be to hide your browser-specific code behind a single function and use feature detection to perform multiple dispatch.

function getStuff() {
    if (browserIsSmart()) {
        return getStuffFromSmartBrowser();
    }
    else {
        return getStuffFromNotSoSmartBrowser();
    }
}

function browserIsSmart() {
    return ('intelligence' in browser);  // Or whatever
}

Here's where it gets messy. Your two functions have different return values. Ideally you'll want the same return value for all related functions, but this isn't always simple. For example, textarea selection in IE8 uses completely different objects than textarea selection in modern browsers. Sometimes you can hide the details (e.g. using the Strategy Pattern), sometimes you can't.

If you can't make it clean, make it obvious.

like image 70
Eric Avatar answered Sep 17 '22 09:09

Eric