Print message on expect() assert failure
Is there a way to print a custom error message when a Jasmine expect()
fails?
As an example, for end to end testing I have an array of web pages and I use one test to go to each URL and assert an element exists on each page. I know I can put every expect()
into a separate test, but I'd rather iterate through the array and log the page URL on failure.
Solution 1:
UPDATE
I see people still are finding this. Later information from the Jasmine team is that there is an undocumented feature on the expect - you can include a custom failure message and it just works:
expect( fields[i].element.exists() ).toEqual(true, field[i].name + ' is expected to exist');
Which is exactly what I was originally looking for.
Original answer follows:
I've been looking for exactly this today, and put a comment here: https://github.com/adobe/brackets/issues/2752
The syntax that has been discussed is an extension to Jasmine to permit a because to be added - so you'd be able to write:
expect( fields[i].element.exists() ).toEqual(true).because( field[i].name + 'is expected to exist');
That is still being discussed after a few years, and may not come to fruition. Another way that I've found to do this is to create a custom matcher. In general I think I'd discourage a custom matcher without being sure you're covering all the bases with it, but in this case we're really checking a true/false value, so the matcher isn't too scary.
We can create the custom matcher with a beforeEach:
beforeEach(function() {
var matchers = {
toEqualBecause: function( value, message ) {
this.message = function() {
return "Expected '" + this.actual + "' to equal '" + value + "' because " + message;
};
return this.actual == value;
}
};
this.addMatchers(matchers);
});
We can then use this matcher to put a message with our failures as such:
expect( field[i].element.exists() ).toEqualBecause( true, field[i].name );
Which will give a failure output including the field name as such:
Expected 'false' to equal 'true' because account_name
Solution 2:
Yes, we can print a custom error message when an expect() failed in Jasmine.
Code Snippet:
it('print a custom error message when an expect failed', function() {
var elemenToBeDisplayed=element(by.css("userName"));
/*custom error message will be displayed if expected condition
failed*/
expect(elemenToBeDisplayed.isPresent).toBe(true,'Write your custom
error message here');
});
Solution 3:
Jasmine 3.3 includes withContext as the officially supported way to specify additional information about the expectation without worrying about which matcher you are using.
Solution 4:
Since Jasmine 3.3, there's a way to do it through withContext
Example:
expect(someValue).withContext('expected someValue to be true...').toBe(true)
See also https://github.com/jasmine/jasmine/issues/641#issuecomment-457037665
Solution 5:
The other answers explain how to hack 'expect', but there is another approach that may solve your problem, though it requires you to flip your thinking around a little bit. Instead of thinking of the 'expect' as your behavior under test, think of all the expectations under a single 'it' call as your behavior under test.
The case where I've come across this problem the most is when I have a function that is doing some kind of intensive parsing and I want to write 20, nearly identical, tests.
Arrange your inputs and outputs like so:
var testDatas = [
{
input: 'stringtoparse1',
output: 'String To Parse 1'
},
{
input: 'stringtoparse2',
output: 'String To Parse 2'
},
{
input: 'stringtoparse3',
output: 'String To Parse 3'
},
];
Now iterate over the list of your test data, and call 'it' from inside the loop like so:
testDatas.forEach(function(test) {
it('should parse for input ' + test.input, function() {
expect(myParser(test.input).toEqual(test.output);
});
});
You get to reduce the amount of extraneous code flying around your tests and you get to format a message for each expectation, or group of expectations.