We explore how to use parametrized tests (example in java, example in c#)
The tests are written using mocha syntax: describe, it. Using chai for expectations: assert.
Note: the example used below (adding to an array) is simple enough to be understood by everybody, without having to explain the domain. The real tests can have a more complicated environment or domain. This is just an example.
Using a custom syntax
This is just an example of some possible syntax, not using any (currently) existing framework.
describe('adding to a list', ()=>{
  newTestCase({description: 'to an empty list',
               input: [],
               parameter: 2,
               expected: [2]})
  newTestCase({description: 'to a non-empty list',
               input: [1],
               parameter: 2,
               expected: [1, 2]})
  it(`${testCase.description}`, () => {
    testCase.input.push(testCase.parameter)
    expect(testCase.input).to.deep.equal(testCase.expected)
  })
})
| Pros | Cons | 
|---|---|
| flexible | |
| verbose | |
| too close to the the real test syntax? | |
how to explain that the it will execute all test cases? | 
|
magic variable testCase: linting, editor complaining about it | 
Using an in-place executor
describe('adding to a list', ()=>{
  const runs = [{description: 'to an empty list',
               input: [],
               parameter: 2,
               expected: [2]},
               {description: 'to a non-empty list',
               input: [1],
               parameter: 2,
               expected: [1, 2]}]
  runs.forEach(testCase => {
    it(`${testCase.description}`, () => {
      testCase.input.push(testCase.parameter)
      expect(testCase.input).to.deep.equal(testCase.expected)
    })
  }
})
| Pros | Cons | 
|---|---|
| flexible | |
flexible to use any testCase variable name (e.g., testCase, tC, run) | 
|
| verbose | |
| using the real test syntax | |
| duplicate the test runner in every case | |
| test-related features mixed with business/domain tests | 
Using it, DAMP
describe('adding to a list', ()=>{
  it('to an empty list', () => {
    const input= [];
    const parameter= 2;
    const expected= [2];
    input.push(parameter);
    expect(input).to.deep.equal(expected);
  });
  it('to a non-empty list', () => {
    const input= [1];
    const parameter= 2;
    const expected= [1, 2];
    input.push(parameter);
    expect(input).to.deep.equal(expected);
  });
});
| Pros | Cons | 
|---|---|
| one test per case | |
| the test is self-contained (DAMP) | 
Using it, DRY
describe('adding to a list', ()=>{
  it('to an empty list', () => {
    const input= [];
    const parameter= 2;
    const expected= [2];
    // use explaining variables
    pushingToMatches(parameter, input, expected);
  });
  it('to a non-empty list', () => {
    // not using explaining variables
    pushingToMatches(2, [1], [1, 2]);
  });
  function pushingToMatches(parameter, input, expected) {
    input.push(parameter);
    expect(input).to.deep.equal(expected);
  }
});
| Pros | Cons | 
|---|---|
| one test per case | |
| no repeated code | |
the testing method pushingToMatches requires access to all test inputs and outputs | 
|
the testing method pushingToMatches breaks the SRP: act and assert | 
Using it, DRY+Fluent
describe('adding to a list', ()=>{
  it('to an empty list', () => {
    const input= [];
    const parameter= 2;
    const expected= [2];
    // use explaining variables
    pushingTo(parameter, input).matches(expected);
  });
  it('to a non-empty list', () => {
    // not using explaining variables
    pushingTo(2, [1]).matches([1, 2]);
  });
  function pushingTo(parameter, input) {
    input.push(parameter);
    return {matches: expected => expect(input).to.deep.equal(expected)};
  }
});
| Pros | Cons | 
|---|---|
| one test per case | |
| no repeated code | |
| readable | |
| verbose, one test per case, when this could be expressed in some other way | |
the testing method pushingTo creates space for the difference in act and assert | 
Sources
- https://rjzaworski.com/2013/01/parameterized-testing-in-javascript
 - http://www.adequatelygood.com/Writing-Testable-JavaScript.html
 - Example in java: here
 - Example in C#: here
 
(This post is a modified version of the session available here)