In the previous article in this series, we saw the
User4.class.php used with our
T5_UserMockingTest to demonstrate testing expectations about how often a method will be called. In this one, we'll review our progress through the various unit tests and discuss some of the issues we encountered.
Unit testing tests the smallest units of a project in isolation — usually individual classes and their methods. We started with a simple test to make sure the Codeception and PhpUnit packages were working. In keeping with the concept of Test-driven Development (TDD), we created our tests, then added the code that would pass them.
Next, we moved on to testing the
User class constructor and validating the
User class fields. Then we added some error handling and tested it.
We extracted our validation code to a separate
Validator class (after creating tests for it using a data provider).
Finally, we discussed Dependency Injection (DI) and used it to pass a stubbed version of our
Validator class into our
Along the way, we saw some bad code, and some bad design. I hope you'll forgive the missteps we took in the process. As I said in an earlier article, it's my belief that you can learn at least as much from bad examples as you can from good ones. In fact, it's time to reveal that our
User class is still flawed.
What should really happen is that the validation of the
User class fields should take place before the
User class is ever involved. It should happen in a controller or in the code that processes a form submitted by the user. It could use our
Validator class for that, so creating the
Validator class and the tests of it wasn't a complete waste of time.
Validating the fields ahead of time would simplify the
User class constructor so that all it does is set the user fields and save the user.
We didn't do that for two reasons. The first is that we wouldn't have been able to show many of the various testing techniques in the previous articles. Our tests of the
User class would have been so simple that there wouldn't be much to learn from them. The second reason is that testing the interaction of the form and the
User class would have involved "integration testing," which we'll look at in future articles in this series. Fully testing the
save() function would also involve integration testing, which is why we didn't bother to create any tests for it.
As you read the previous articles, you may have noticed some tests that could (or should) have been performed because there was code in our classes that would never be executed in our tests. Rather than reading through all the code looking for them, we can use a very sophisticated PhpUnit add-on that measures Code Coverage. We'll take a closer look at that in the following articles.
In the next article, we'll see how to set up Codeception to produce code coverage reports.
Looking for high-quality, MODX-friendly hosting? As of May 2016, Bob's Guides is hosted at A2 hosting. MODX will work fine at most hosting services, but having a MODX-friendly host can prevent a lot of frustration. Better yet, the A2 Solid-State-Drive servers are configured to handle the many Ajax and database calls made by MODX — especially the MODX Manager. My Manager runs about four times as fast as it did on my previous host. I particularly recommend the Swift package with the Performance Plus option.