KissTest, a Simple, Fast, and Beautiful Unit Test Framework for PHP
PHPUnit is a great testing framework. However, over time I began to find myself wishing it had certain features. So I created KissTest. It is a Keep-It-Simple-Straightforward (KISS), very fast, and absolutely gorgeous xUnit style unit test library.
As you can see in the screenshot, the display of the results is right in the browser. Everyone loves the command line and I am no different. However, there is something to be said for seeing the results laid out beautifully like this. Also, the PHP CLI binary is technically different from the one that is used to serve web pages. Generally, I try to keep the execution environment for the development environment and the production environment as close as possible. In fact, my development environment is identical to the production environment except it is running in VirtualBox. KissTest facilitates this. Sweet!
At all testing levels detailed metrics for all tests are displayed. This includes the the entire test suite, each unit test file, and each test case. Now you can easily and immediately know if any tests are taking an excessively long time to complete. I don’t know about you, but I have a very low tolerance for slow tests.
If you have lots of tests in your project, and you should, then you may wonder if it would be overwhelming to display the results of all of those tests on one large browser page. To eliminate this issue, several features are built right in. First, at the top of the results a nice and compact table of contents for all of your tests is provided. You can easily see which one is failing. Clicking on the table of contents entry for the failing test will take you directly to the results for that unit test file.
Once at the results for the unit test file, it will be immediately apparent which test case is failing. Each failing test case provides a couple of pieces of information to help diagnose why it is failing. First, both test operands (arguments) are displayed. This allows you to immediately see if they are not equal, etc. Second, each assertion in your test case provides the ability to have a customized failure message. This is super handy determining which assert is failing for test cases containing multiple asserts. To get back to the table of contents, a handy link is always provided to go right back to the top and the table of contents.
KissTest promotes great test case naming practices. For the method name of each test case, all underscores are converted to spaces when the results are displayed in the browser. This provides a display of the name and purpose of the test case in a natural language automatically.
Arguably, testing in the browser could be considered faster than testing from the command line. This is because rerunning the test suite is as simple as pressing refresh (F5 or Ctrl+R). Additionally, KissTest itself is designed to be extremely fast. A major design goal was to minimize the overhead for the testing framework. This includes both the assertion portion of the framework and the mocking/stubbing portion of the framework. No eval, no dynamic injection, and no other language features are used that can slow down PHP.
On problem I have had was teaching rookie developers both the tools and practices needed for any professional developer. One of those is generally TDD and unit testing in particular. I need my developers to be as useful as possible as quickly as possible. This means I don’t have time for them to spend days learning specialized configuration or complicated usage scenarios. Frankly, time is money. Generally, I want my developers to spend a minimal amount of time learning tools and frameworks. KissTest can be learned in 10-15 minutes. Additionally, anything a developer does not understand can be figured out in just a few minutes of code inspection of existing usage. This is because configuration is kept as simple as possible for new developers by keeping it all in PHP. No XML, no annotations, and no *.ini files. Yay!
To further eliminate cognitive load, the stubbing and mocking solution has been merged into the same concept. In KissTest stubs and mocks are the same idea except for one difference. If you are not asserting on what the mock is doing or how it is being used, then it is just a stub. If you are, then it is a mock. Now, of course, this would be terrible if the mocking functionality was slow like many other frameworks. However, this is not the case here. In KissTest, stubs/mocks are extremely fast. It is literally a O(1) array insertion. No dynamic reflection, injection, method addition, magic, or other hand-wavy stuff going on here. Awesome!
The project is a Composer package using Packagist for easy use. It is hosted on GitHub and is fully documented. Please feel free to check it out and provide input, pull requests, discussion, and feedback.