/ jasmine

Running a Test with Multiple Test Cases in Jasmine

If you have previously used testing frameworks such as NUnit or JUnit, you would know there's the ability to run one test with a number of different test cases by simply decorating your test with the test cases. An example from NUnit Documentation is:

[TestCase(12,3,4)]
[TestCase(12,2,6)]
[TestCase(12,4,3)]
public void DivideTest(int n, int d, int q)
{
  Assert.AreEqual( q, n / d );
}

At work, I've been doing a lot of unit testing of our Angular 4 project using Jasmine. I've found the need to run a singular test multiple times with different test cases just like in the above example. However, to my knowledge, there's no functionality that comes with Jasmine to easily do this.

The initial way I ran test cases was through creating an array of test cases within my it function like this:

describe('divideTest', () => {
    it('should divide correctly', () => {
        const testCases = [
            { n: 12, d: 3, q: 4 },
            { n: 12, d: 2, q: 6 },
            { n: 12, d: 4, q: 5 } // Will fail!
        ];
        
        testCases.forEach(test => {
            expect(n / d).toEqual(q);
        });
    });
});

This worked fine and will run all test cases. However, it runs all test cases in the one function and if a test case fails, Jasmine will not notify us exactly what exactly case failed. We can see the third test case will obviously fail in this case ({ n: 12, d: 4, q: 3 }), Jasmine will show the error as:
Screen-Shot-2018-03-27-at-3.34.58-pm

We can see the test failed, but we can only see it expected a result of 3 to be 5. From looking at this alone, I'd have no idea what caused the actual failure. To see which test case it actually was, we'd have to scan through each case and see which case matches. For a small amount of simple test cases, this shouldn't be a problem (like in this example). But when you are constructing tests around more complex functions, it will be much harder to find the test case that failed.

What you can do is create more descriptive test cases by simply moving the forEach loop outside of the it statement like so:

describe("divideTest", function () {
  const testCases = [
    { n: 12, d: 3, q: 4 },
    { n: 12, d: 2, q: 6 },
    { n: 12, d: 4, q: 5 }
  ];

  testCases.forEach(test => {
    it(`should divide ${test.n} by ${test.d} correctly`, () => {
      expect(test.n / test.d).toEqual(test.q);
    });
  });
});

You'll notice that I made the should description more verbose. This makes it easy to understand which case failed and will output:
Screen-Shot-2018-03-27-at-3.40.34-pm

Now we can easily see which test case resulted in a failure. You can also go further by specifying the index of the test case you are running like this:

describe("divideTest", function () {
  const testCases = [
    { n: 12, d: 3, q: 4 },
    { n: 12, d: 2, q: 6 },
    { n: 12, d: 4, q: 5 }
  ];

  testCases.forEach((test, index) => {
    it(`should divide ${test.n} by ${test.d} correctly (testcase: ${index + 1})`, () => {
      expect(test.n / test.d).toEqual(test.q);
    });
  });
});

The verbosity of your test case is ultimately up to you and you should customise it to your needs.

Hope this helps you make more easy to read tests using Jasmine!