Unit tests are used for testing source code to see if it contains deals with inputs as we expect. Unit tests are supported by the majority of frameworks. There are several different PHPUnit tests and they might differ in syntax. In this example we are using PHPUnit.
PHPUnit Data Providers
Test methods often need data to be tested with. To test some methods completely you need to provide different data sets for every possible test condition. Of course, you can do it manually using loops, like this:
And someone can find it convenient. But there are some drawbacks of this approach. First, you'll have to perform additional actions to extract data if your test function accepts several parameters. Second, on failure it would be difficult to distinguish the failing data set without additional messages and debugging. Third, PHPUnit provides automatic way to deal with test data sets using data providers.
Data provider is a function, that should return data for your particular test case.
A data provider method must be public and either return an array of arrays or an object that implements the Iterator interface and yields an array for each iteration step. For each array that is part of the collection the test method will be called with the contents of the array as its arguments.
To use a data provider with your test, use @dataProvider annotation with the name of data provider function specified:
Array of arrays
Note that dataProviderForTest() returns array of arrays. Each nested array has two elements and they will fill necessary parameters for testEquals() one by one. Error like this will be thrown Missing argument 2 for Test::testEquals() if there are not enough elements. PHPUnit will automatically loop through data and run tests:
Each data set can be named for convenience. It will be easier to detect failing data:
As you can see, simple iterator also works.
Note that even for a single parameter, data provider must return an array [$parameter]
Because if we change our current() method (which actually return data on every iteration) to this:
Or change actual data:
We'll get an error:
Of course, it is not useful to use Iterator object over a simple
array. It should implement some specific logic for your case.
It is not explicitly noted and shown in manual, but you can also use a generator as data provider. Note that Generator class actually implements Iterator interface.
So here's an example of using DirectoryIterator combined with generator:
Note provider yields an array. You'll get an invalid-data-provider warning instead.
Let's say you want to test method which throws an exception
You can do that by enclosing the method call into a try/catch block and making assertions on execption object's properties, but more conveniently you can use exception assertion methods. As of PHPUnit 5.2 you have expectX() methods available for asserting exception type, message & code
If you are using earlier version of PHPUnit, method setExpectedException can be used in stead of expectX() methods, but keep in mind that it's deprecated and will be removed in version 6.
Testing class rules
Let's say, we have a simple LoginForm class with rules() method (used in login page as framework template):
In order to perform tests on this class, we use Unit tests (checking source code to see if it fits our expectations):
How exactly Unit tests can help with (excluding general examples) in here? For example, it fits very well when we get unexpected results. For example, let's take this rule from earlier:
Instead, if we missed one important thing and wrote this:
With dozens of different rules (assuming we are using not just email and password), it's difficult to detect mistakes. This unit test:
Will pass our first example but not second. Why? Because in 2nd example we wrote a pattern with a typo (missed + sign), meaning it only accepts one letter/number.
Unit tests can be run in console with command: phpunit [path_to_file]. If everything is OK, we should be able to see that all tests are in OK state, else we will see either Error (syntax errors) or Fail (at least one line in that method did not pass).
With additional parameters like --coverage we can also see visually how many lines in backend code were tested and which passed/failed. This applies to any framework that has installed PHPUnit.
Example how PHPUnit test looks like in console (general look, not according to this example):
This modified text is an extract of the original Stack Overflow Documentation created by following contributors and released under CC BY-SA 3.0