Asserts can help in testing code.
In the case of assert.equal
, we hope that the method being tested (with valid input) executes to completion and returns a value without throwing any errors. assert.equal
compares the returned value to an expected value. If the assert fails, then we know that something is wrong with our code (perhaps in logic or syntax or something else).
Have a look at the slightly modified version of your code for assert.equal
,
const inputNumber = 12;
const expected = "12";
const actual = Rooster.timeAtDawn(inputNumber);
console.log(actual);
console.log("Before Equal Assert");
assert.equal(actual, expected);
console.log("After Equal Assert: Success");
// Output:
// 12
// Before Equal Assert
// After Equal Assert: Success
In the above code, we are assigning the result of our method call to the constant variable actual
, i.e. in the line:
const actual = Rooster.timeAtDawn(inputNumber);
actual
has the value "12"
as confirmed by the console.log
statement. If for some unexpected reason, timeAtDawn
throws an error, then it isn’t the assert statement alerting us to the error. We don’t even get to the assert statement. In the above code, the string “Before Equal Assert” will not be printed, because the error will be thrown during the call to timeAtDawn
. If an error gets thrown even for a valid input, then we know something is wrong with the code.
If no error is raised, and we get to the assert statement, then at least we know that the method returned some value (whether correct or incorrect remains to be determined). If the assert is silent, then we pass the test successfully. Suppose const inputNumber = 12;
and const expected = "12"
but timeAtDawn
returns say "10"
instead of the expected "12"
. then timeAtDawn
won’t throw an error. But, the assert.equal
will throw an AssertionError
alerting us that timeAtDawn
failed to return the expected output.
Contrast this with the assert.throws
scenario. When an invalid input is passed to timeAtDawn
, it is supposed to throw an error. This is by deliberate design. But, for testing, we don’t want to throw an error which halts execution of the test program. If timeAtDawn
throws an error for the reason expected by us, then assert.throws
silently signals that all is well, the assertion has passed and we don’t need to halt the program. So we can move on to test other assertions or run more code.
const inputNumber = 26;
const expected = RangeError;
// const actual = Rooster.timeAtDawn(inputNumber);
const actual = () => Rooster.timeAtDawn(inputNumber);
console.log(actual);
console.log("Before Throws Assert");
assert.throws(actual, expected, "Throw Assert Failed");
console.log("After Throws Assert: Success");
// Output:
// [Function: actual]
// Before Throws Assert
// After Throws Assert: Success
In the above code, look at the commented out line
const actual = Rooster.timeAtDawn(inputNumber);
This is the same as we did for assert.equal
. Since the input is invalid, so timeAtDawn
will throw a RangeError
and the program will halt. We could look at the terminal to see details about the error, but it defeats the purpose of automated testing as opposed to human inspection. timeAtDawn
was designed in such a way that out of range inputs would cause an error, so this is not aberrant behavior.
By using,
const actual = () => Rooster.timeAtDawn(inputNumber);
we haven’t invoked the function yet.
console.log(actual)
shows [Function: actual]
as the output, as opposed to the assert.equal
case where actual
stored the value returned by timeAtDawn
.
assert.throws
will execute the function call in actual
. An error will be thrown by timeAtDawn
, but assert.throws
will compare this error to the expected
error. If the errors are the same, then the assert is true and timeAtDawn
threw an error exactly when we wanted it to and for the reasons we wanted it to do so. The program will not halt, the string "After Throws Assert: Success"
in the above snippet will print and we will move on to test other assertions or run other code.
Suppose the expected error was RangeError
, but timeAtDawn
threw a TypeError
instead. Then, the assert will fail. The thrown error was raised for unanticipated reasons, so the assertion is false. The program will halt with the error shown in the terminal. In this case the program didn’t halt because of timeAtDawn
throwing an error, but because the assert failed due to a mismatch between the actual and expected errors.