All our tests successfully passed and now only one test remaining on our test list (test #4):
Where the previous test (test #3) was the sunshine (or happy path) scenario, our current test takes the rainy side. As such we will test that, when a user types in a doc. amount which does not equal the total amount of the (2) lines, the system, no, the verification fails. Hey, did I want to write down the system fails? Uhhh, no, I guess I wanted to say the system throws an error. Apparently I had glanced at test #4 on our test list and realized that we were not to check any error throwing. Aha, what does our requirement actually say? (See Test-Driven Development in NAV - By Example.)
To prevent a user posting purchase invoices headlong he has to enter manually the total amount of the invoice lines in a field on the invoice header and only when header amount and lines total match can the document be posted.
We haven't paid any attention to it since we defined our initial test list and, clearly, there are more tests to be defined. What about these two?
And what about the error throwing? Do you see it mentioned in the requirement? You get what I mean? As stated before:
... no requirements (i.e. no tests), no code, ...
Of course we could wonder, no: argue, regarding this specific part, about the validity of our requirement. As this series is not about requirement gathering, though, we leave it as it is (for now as we will touch upon it later for other reasons).
Now, what were we about to do? Test #4! Except for one word an exact copy of test #3, isn't it?
Let's practice our C&P competence once more by creating FailingVerification from the SucceedingVerification function.
// Create a purchase headerPurchHeader."Doc. Amount" := 2.5; //Mimic an incorrect manual input of the total doc. amount PurchHeader.INSERT(TRUE);
// Create two purchase lines to the headerCreatePurchLine(PurchHeader."No.",10000,1);CreatePurchLine(PurchHeader."No.",20000,2);
//Check if manually entered total doc. amount equals the line amountsAssert.IsTrue(PurchHeader.VerifyDocAmount,'Verify Doc. Amount')
So we can skip step 3 (Implement just enough to compile) and ...
But isn't that strange? Isn't this exactly what we want tot happen? That VerifyDocAmount 'fails', i.e. returns FALSE and thus Assert.IsTrue fails? True, but from a test management perspective we are expecting the system to mark it with a SUCCESS (and successfully continues with any next statement).
So how do we go about this? Here is where the C/AL function ASSERTERROR comes in:
You use ASSERTERROR statements in test functions to test how your application behaves under failing conditions. The ASSERTERROR keyword specifies that an error is expected at run time in the statement that follows the ASSERTERROR keyword.
Let's give it a try and ...
//Check if manually entered total doc. amount does not equal the line amountsASSERTERROR Assert.IsTrue(PurchHeader.VerifyDocAmount,'Verify Doc. Amount')
Cross your fingers and ...
Oops, sorry for that. I should have warned you. [+o(]
Ready. Fini. Gatavs. Spreman. Klaar. ... !!!
Wait, wait, Luc. By all means test #4 is successfully passing and as such our initial test list has been taken care of, but we have added two new tests, and, BTW, what about ...
Production code is OK, but we still have an issue on our to-do-list. Remember: the duplication in PIwithTwoLines and SucceedingVerification. With our new test function FailingVerification we are adding even more duplication to our code. But we'll keep it on our to-do-list even though it's endangering our code as we are running against the second rule of TDD, i.e. running the risk of forgetting to remove the duplication (actually already being triplication).
The simple reason is that within the NAV test libraries MS has provided us with a great number of test (related) functions that will help us to get rid of this duplication and I have planned to tackle this in a separate post. For the impatient among us: have a look at codeunits 132200 (Library - SCM) and 134328 (Purchase Invoice).
OK let's cross of test #4 and ...
... where one of the newborns (test #5) is awaiting us.