It looks like this:
The old functionality is still there above these tools, but I omitted it from the screenshot for clarity.
So what is this doing? Well the Record ID tools are adding a row number onto both datasets and then the transpose tool uses this as a key and all other fields (importantly including unknowns) as data fields.
The Join then joins the two streams together on the row number and field name.
Finally the message tool is configured:
Whenever the data differs we get a nice error message:
Message (30) Unexpected Value - Field:Total Row:1 Expected:1 Actual:0
With this in place we can write our next tests. So just a quick reminder of the TDD work cycle:
- Write a test for a piece of functionality which will fail.
- Write some code which makes the test pass.
- (Optionally) Re-factor your code. Without adding any new functionality and without breaking any tests.
Write a Failing Test
The next smallest piece of functionality I could think of is this:
"Single Field Named Field1 With Value 1 Gives Total of 1"
I add a new module to my test folder called Single Field Named Field1 With Value 1 Gives Total of 1.yxmd and copy the module from my first test
and the Expected data to
Then I save the module and run my test runner which gives me this log
Great a failing test with a clear and precise error message.
Make The Test Pass
So next the smallest amount of code to make the test pass. Easy open up our Add Totals macro
And just change the hard coded formula value from 0 to 1. Run the tests again
Success!
Write a Failing Test
Well I can quickly see where my current implementation is going to fall down. What if my user's data contains something other than the value 1? So let us write a test to exercise that:
"Single Field Named Field1 With Values 1,2,3 Gives Totals 1,2,3"
So again copy and paste one of our existing tests and update the data
Incoming test data
Expected data
And run the tests
Fails as expected and again a pleasing and exact error message.
Make The Test Pass
Again easy enough to make this test pass. We just update our formula to [Field1]
and
Oh dear. Our new test is passing, but our first test "Adds A Column Called Total" has failed. What's happened?
So the error message is telling us that our new formula is giving a string result. If we recall our first test our fields didn't have any data in them at all. This means that the text input tool has no data to use to determine the type of Field1 so defaults to a type of V_WString. So yes trying to use that in a formula which should result in a double is an error.
But that's not a very good error for users of our macro. It refers to internal tools in our macro and doesn't tell the user what to do to fix it. We can do better than that, but not right now. Right now we are working on making our tests pass having added a new one. We shouldn't be adding any new functionality.
In TDD it is often helpful to have a small list somewhere (I tend to scribble on a pad on my desk) of tests that you are going to add in the near future, then when you find things like this you can simply add them to the list and get back to the actual problem you are working on. So we'll do just that
Tests To Add
- If a user tries to total a string column they get a meaningful error message.
This is some of the strength in the TDD approach you are exploring ways in which your macro will be used and can break as you develop it.
So back to the problem at hand. Our first test was never meant to test anything about wrong field types, it was just supposed to check the Total column got added. So let's just fix up the test with a couple of select tools to force our columns to be numeric types
and
All good!
Write a Failing Test
"Two columns Field1, Field2 With Values 1,2,3 Gives Totals 2,4,6"
Again the test looks identical to our previous ones just with updated Test and Expected data.
Make The Test Pass
Now we're beginning to get to some real implementation. The naive fix of updating our formula to [Field1] + [Field2] isn't going to cut it as it would fail on the tests which don't have Field2.
I need to dynamically get the names of my fields, use them to build up my formula and then apply that formula to my data.
Which implemented looks like this
Quick overview from left to right:
- The field info tool gets all of the field names
- The summarize tool builds the total formula by concatenating the field names with a + separator
- The formula tool sets up the Type, Size and Field Name that we need for the dynamic formula tool
- The dynamic formula tool applies the formula to the data
Run the tests
and not only do we know we have implemented out latest piece of functionality, but we can also see that we have not broken any functionality that we previously added.
Next Time
Now we are beginning to get something that is beginning to look like it might be useful. Looking at my list of future tests I think now is going to be a good point to tackle that better error message if my user tries to total a string field, which we will look at in my next post.