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?
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?
Share Improve this question asked Mar 21, 2014 at 21:42 redrumredrum 4941 gold badge4 silver badges14 bronze badges 1-
It is bad to have conditionals in your test. Branching in a test is usually considered a code smell. You're better off asserting something like
browser == LegacyBrowser || realTestCondition
. This will short circuit if the test shouldn't run on a legacy browser. – munk Commented Mar 21, 2014 at 21:58
1 Answer
Reset to default 10It'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 pletely 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.