There should be a way to force running a test not by simply checking whether it's defined with iit
(as it is now) but also by scoring each ocurrentce of iit
and only running those with the highest score:
ddescribe('Module: foo (to run tests only for this very module)', function () {
ddescribe('Service: foo to run tests only for this service', function () {
iit('should run because it is forced');
});
describe('Service: bar', function () {
iit('Now runs because it is forced. I suggest it should not run because it has less ddescribes on the "way" to this iit then the first one in this snippet.');
});
})
The same expressed using the suite factory:
ddescribe('Module: foo (to run tests only for this very module)', function () {
function mySuiteFactory(data) {
return function () {
iit('should run because it is forced And now it runs 2 times - for both describes', function () {
// use the `data` given to the factory.
});
// I suggest running the test above only when it's top scored.
}
}
ddescribe('Service: foo to run tests only for this service', mySuiteFactory(data1));
describe('Service: bar (where the test should not run despite the fact it is forced)', mySuiteFactory(data2));
})
Real life example:
I have a simple service that is responsible for converting different forms of an expression with the same meaning. I have 5 ways to express the same thing: 4 of them are strings and the 5th is a collection of object. Each way (or as I call it: a variant) is used in different circumstances but all of them are capable of expressing the same logic.
I built a factory that returns the suite of cases that cover all the conversions. A fixture with the same thing expressed in 5 variants is the argument of the factory. Result of calling this factory may be passed as the 2nd argument of describe
:
function getCrossTestsFor(data) {
return function () {
let converter;
beforeEach(inject(function (converterService) {
converter = converterService;
}));
it('should get converted from `variant1` to `variant2`', function () {
expect(converter.variant1.toVariant2(data.variant1)).toBe(data.variant2);
});
// And 19 more "its": 5 variants = 5*(5-1) "its"
}
}
The same may be expressed without returning wrapped in an anonymous function but this way it can be passed as the 2nd argument of describe right away.
Then I define a suite like this:
describe('value `undefined`', getCrossTestsFor({
variant1: undefined,
variant2: undefined,
variant3: undefined,
variant4: undefined,
variant5: undefined,
}));
describe('value "empty string"', getCrossTestsFor({
variant1: '',
variant2: '',
variant3: '',
variant4: '',
variant5: [],
}));
And I have many such sub-suites (all in all: n*20 tests).
When something breaks I get many errors due to the nature of how the the suite is defined: When something breaks it affects more than one it
either because of the error in decoding a variant or in encoding the decoded data back to some other.
I have meaningful error messages like this:
FAIL: value "empty string" should get converted from `variant1` to `variant2`
But I cannot run only this single test.
I tend to fix tests one by one by forcing only one to run. I don't know if it's a good practice generally but it's a good one in my case ;) I do this by forcing certain suites or certain tests. But it's not possible in this case, when suite factory pattern is used.
I also tried to define it
s in loops but though it seems to be a cleaner way to test large portions of data It came out that this pattern is far more difficult to debug: Not only I have to force the it
in loop (or loopsas it was in my case) but I also have to make sure the loop (or each of the loops) is run only once to run a single test. Effectively I have to comment out large portions of my data fixture apart from of just using the jasmine-karma feature of forcing a test or a suite (iit
, ddescribe
).
Back to the topic: Putting ddescribe
before any suite results in running "only" 20 of my tests. Some of them are broken, some are not.
Putting iit
before one of the tests that fail results in running n
tests (not one!). This is because in fact this iit
ed test is present in n
describes (see the abstract example at the beginning).
I found the way to extract only one of my (n*20) tests and focus on fixing this one: I force (ddescribe
) the suite that fails but instead of iit
ing the failing test one I exclude (xit
) all the others.
Only this combination results in running the particular test that I want to focus on. But the procedure is laborious.
I wonder if it might be simplified.