There are two terms we use often when talking about unit tests: tests and assertions. It’s important to know the distinction between the two and to fully understand what each refers to.

When we use the term test, we are referring to a group of one or more assertions, and an assertion is one “check” within the the test to determine if a value is equal to what we expect. For example, the following is one test with a single assertion:

function test_sample_string() {

	$string = 'Unit tests are sweet';

	$this->assertEquals( 'Unit tests are sweet', $string );
}

This is a unit test with two assertions:

function test_sample_string() {

	$string = 'Unit tests are sweet';

	$this->assertEquals( 'Unit tests are sweet', $string );
	$this->assertNotEquals( 'Unit tests suck', $string );
}

This is a set of two unit tests, one with a single assertion and one with two assertions:

function test_sample_string() {

	$string = 'Unit tests are sweet';

	$this->assertEquals( 'Unit tests are sweet', $string );
}

function test_sample_number() {

	$number = 5;

	$this->assertEquals( 5, $number );
	$this->assertNotEquals( 2 + 2, $number );
}

These are over simplified examples, but they should serve to provide a better understanding of what a test is and what an assertion is.

Each assertion you make checks one expected value against the value returned by your function or method. For example, in part one of this series, we saw a unit test that looks like this:

public function test_get_sales_by_date() {
 
	$stats = new EDD_Payment_Stats;
	$sales = $stats->get_sales( 0, 'this_month' );
 
	$this->assertEquals( 1, $sales );
}

This is asserting (checking) that the total number of sales for the current month is 1. If it is anything other than one, our test will fail.

We could add additional assertions to this test to check additional possibilities. For example:

public function test_get_sales_by_date() {
 
	$stats = new EDD_Payment_Stats;
	$sales = $stats->get_sales( 0, 'this_month' );
 
	$this->assertEquals( 1, $sales );
	$this->assertGreaterThan( 0, $sales );
	$this->assertLessThan( 10, $sales );

}

Now, it may seem a little silly to have all three assertions because if the first test fails, we know that $sales isn’t 1. Right? Well, maybe. You have to keep in mind things like data types. What if $sales was returned as a string instead of an integer? Would that make a test fail? In this case, not likely, but for your unit tests, depending on what you’re testing, the data type might be really important. By making multiple assertions, we can better assure that our code is functioning as expected.

Take our unit tests for our get_tax() function from part one as an example. The get_tax() function is supposed to return the amount of tax charged on the amount passed to the function. so our unit tests might include multiple assertions to determine if amounts given in various formats all return as expected:

public function test_get_tax() {

	// Assume a 10% tax rate and assume all amounts are rounded to two decimal places

	$this->assertEquals( '10', get_tax( 100 ) );
	$this->assertEquals( '10', get_tax( '100.00000000000' ) );
	$this->assertEquals( '10', get_tax( '100.0022' ) );
	$this->assertEquals( '1', get_tax( '10' ) );
	$this->assertEquals( '1.01', get_tax( '10.10' ) );

}

In this example, we have one unit test for our get_tax() function, but it makes multiple assertions in order thoroughly test different possibilities for amounts that could be passed to it.

Some people will tell you that unit tests should only ever contain a single assertion, and I don’t entirely disagree with them, but I would encourage you to make your own decision. Personally, I think it depends on what the test is and what the function or method you’re testing does. In our get_tax() rate example, I feel it makes sense to have multiple assertions, since we’re determining if the get_tax() function properly returns the amount expected given a variety of inputs.

Throughout this part and the previous parts of this series, you have seen a few example of assertions we can use with PHPUnit. So far we have seen:

  • assertEquals()
  • assertNotEquals()
  • assertGreaterThan()
  • assertLessThan()

These are all very useful and will get you a long ways, but there are actually many, many more provided by PHPunit and the WordPress testing suite. The PHPUnit Appendix has a long list of the available assertions.

In the next part of this series we will begin writing actual unit tests for Restrict Content Pro and really get our feet wet with unit testing.

  1. curtismchale

    See I’d organize each assertion in the get_tax function in to a single test and call it what it’s actually checking for.

    Like the second one `testgettaxDealsWithLotsOfZeros` then your single test failure means that you can tell exactly what is going wrong.

    • Pippin

      Yep, makes sense, though since PHPUnit reports back the exact line number that a test fails on, I’m not sure there’s much difference between the two beyond personal preference.

Leave a Reply