There we go. Let's turn to our companion on this journey, our Test List, pick out our first test:
Create PI (purchase invoice) with 1 line and check that total line amount is calculated right
Create PI with multiple (2) lines and check that total line amount is calculated right
Create PI with multiple lines and check that doc. amount verification succeeds
Create PI with multiple lines and check that doc. amount verification fails
... and sing the RED/GREEN/REFACTOR mantra:
So let's open our NAV classic client (CC) and create our first test codeunit:
... and define our first test based on our Test List entry #1, name it PIwithOneLine and first make it create a purchase header:
// Create a purchase headerPurchHeader.INSERT(TRUE); //TRUE ensures that the system assigns a unique number to the header
Of course, no surprise; lazy me counting on the compiler, my other companion, to tell me to define the PurchHeader variable.
Now continue to create one purchase line to this header (and not to forget the define the appropriate variable). The function will look like this:
// Create one purchase line to the headerPurchLine."Document No." := PurchHeader."No.";PurchLine."Line Amount" := 1;PurchLine.INSERT;
I can tell you: it compiles and we are set to complete this test code. We have a purchase header and a line and now we want to check if the amount on the line (indeed only one, which feels stupid, doesn't it?) equals the total document amount calculated on the header. For this we could write a simple IF-statement, but we will be using one of the functions in the the test libraries provided by MS: codeunit 130000 (Assert). This way we assure that our test code contains easy recognizable (test) patterns.
In our case we will apply the AreEqual method from the Assert library; i.e we assert that the amount on the line is equal to the calculated (total) line amount:
//Check if line amount equals the line amount calculated by CalcDocAmountAssert.AreEqual(PurchLine."Line Amount",PurchHeader.CalcDocAmount,'Calc. Doc. Amount')
Our first test is ready so we will ...
... which shows RED:
Indeed we so far only created our test and against this we will ...
... i.e. implement just enough production code to get it compiled. What do we do and where do we do this?
We build the CalcDocAmount function there where it belongs: on the Purchase Header table (38), returning an amount, being of type decimal:
CalcDocAmount() Amount : Decimal
Is that all? Yep, that's all. It compiles. "Just enough to compile", you know.
Does it make sense? According to the mantra it does, but probably in the context of all our experience in writing code for NAV applications, nope. Feel it itching? Just let and never mind, we follow the rules of the TDD game and ...
Well ... almost. We first have to compile codeunit 60000 to be able to run it. Pfff, it compiles! [^]
Aha, this is new (for those who have never worked with the testability features): the result window of a single test codeunit! It's telling us that the PIwithOneLine test function failed (first FAILURE), making BTW the whole run fail (last FAILURE). In between we get informed on the result of the Assert.AreEqual statement. The expected value (of the CalcDocAmount function as you might recall) was 1, being the amount of that single purchase line, but turned out to be 0. Sure, my CalcDocAmount function did not return any specific value, so it yields by default 0.
OK, let's go for GREEN as fast as possible and ...
Indeed just enough "to make the test pass". Fake it till you make it!
Compile and ready to ...
...? Are you? I am, so here we go: GREEN
Anything to refactor? Looking at both the production and test code we wonder if we have something to refactor. No duplication of code to be found, hence we could be moving on to the next step.
Even though we have no duplication we might want to make our code a bit more generic, i.e. make it work for any "one lined" purchase invoice having any amount on the line. Consequently we ...
Let's change the code a little bit so that the line amount is 'generic':
// Create one purchase line to the headerPurchLine."Document No." := PurchHeader."No.";PurchLine."Line Amount" := RANDOM(100);PurchLine.INSERT;
And now ...
By all means CalcDocAmount can no longer fake it: it's failing clearly.
Nothing is going to stop us to get GREEN ... so let's ...
Thus we have to be more intelligent and collect the line amount from the relevant purchase line:
PurchLine.SETRANGE("Document No.","No.");IF PurchLine.FINDFIRST THEN EXIT(PurchLine."Line Amount");
Anything to refactor? No.
We have completed the first entry on our Test List and are ready to move to the next. Stay tuned for my next blog entry. [O]