Do WordPress unit tests exist?

Clarifying a terminology issue.

There are “no” unit tests

The wp-browser module for Codeception was born to make WordPress testing easier and is not meant to enforce any rule.
Sticking to a stricter TDD terminology there are no WordPress “unit” tests.
This might seem counter intuitive so here’s an example.

Admin notices

I need to show, in the backend, notice to users; since I’m a lazy developer I will write a class that’s responsible for the rendering of such notice; a basic one to start with that I will iterate over to suit my later needs.

<?php

class AdminNotice implements AdminNoticeInterface{
    protected $message;
    protected $notice_class;

    public function __construct($message = '', $notice_class = 'updated') {
        $this->message = $message;
        $this->notice_class = $class;
    }

    public function get_notice(){
        return empty($this->message) ? '' : sprintf($this->template(), $this->data());
    }

    public function the_notice(){
        echo $this->get_notice();
    }

    protected template(){
        return '<div class="%s">%s</p></div>';
    }

    protected data(){
        return array(
            $this->notice_class,
            $this->message,
        );
    }

}

Now this class can be unit tested in the stricter sense.
This means I can write a code like this to test it in, say, Codeception:

<?php

class AdminNoticeTest extends \Codeception\TestCase\Test {

    function test_will_not_render_if_empty_message(){
        $sut = new AdminNotice('');

        $notice = $sut->get_notice();

        $this->assertEmpty($notice);
    }

    function test_will_render_message(){
        $sut = new AdminNotice('My message');

        $notice = $sut->get_notice();

        $this->assertContains('My message', $notice);
    }
}

The reason I can write this code in a strict definition “unit” test is that the class under test is not using any WordPress defined function to work and hence will not require a bootstrapped WordPress installation to run.

Functional tests

I later need to show the user a notice about a conflicting plugin setting and would like to be as helpful as possible: if the user can manage options I’d like to link the user to the option edit screen otherwise tell the user to report to someone with that capability.
Here’s my new notice class extending the base one:

<?php
class ConflictingOptionAdminNotice extends AdminNotice {
    protected $option_pretty_name;
    protected cta_url;

    function __construct($option_pretty_name, $cta_url) {
        $this->option_pretty_name = $option_pretty_name;
        $this->cta_url = $cta_url;
    }

    function template(){
    return '<div class="error"><p>Option %s is conflicting. %s</p></div>'
    }

    function data(){
        if(current_user_can('manage_options')){
            $frag = sprintf('<a href="%s">Edit it!</a>', $this->cta_url);
        } else {
            $frag = 'Ask an administrator to edit it.';
        }

        return array(
            $this->option_pretty_name,
            $frag,
        );
    }
}

This class cannot be unit tested in the stricter sense.
Since it’s using the current_user_can function either I stub the function in a unit test like this

<?php
function current_user_can(){
    $global $current_user_can;
    return $current_user_can;
}

class ConflictingOptionAdminNoticeTest extends \Codeception\TestCase\Test {

    public function test_shows_non_actionable_notice_if_user_cannot_manage_options() {
        global $current_user_can;
        $current_user_can = false;
        $url = 'http://g.com';
        $sut = new ConflictingOptionAdminNotice('Option One', $url );

        $notice = $sut->get_notice();

        $this->assertNotContains($url, $notice);
    }
}

or use a functional test (again in the stricter sense) that will have WordPress bootstrapped using something like the WP Loader wp-browser module

<?php

class ConflictingOptionAdminNoticeTest extends \Codeception\TestCase\WPTestCase {

    public function test_shows_non_actionable_notice_if_user_cannot_manage_options() {
        global $current_user;
        $user = $this->prophesize('WP_User');
        $user->has_cap('manage_options')->willReturn(false);
        $current_user = $user->reveal();
        $url = 'http://g.com';
        $sut = new ConflictingOptionAdminNotice('Option One', $url );

        $notice = $sut->get_notice();

        $this->assertNotContains($url, $notice);
    }
}

Of the two I will always go for the latter as it is the most maintainable one and since this requires a bootstrapped WordPress installation to run I’d test the first class in the unit suite and the second one in the functional suite.

codecept generate:test unit AdminNotice
wpcept generate:wpunit functional ConflictingOptionAdminNotice

A matter of taste

One could feel the ConflictingOptionAdminNoticeTest class really is a unit test, although requiring WordPress to run, and should be filed in the unit test suite: this would be legit and fine.
I like stricter definitions but this is, again, a matter of personal taste.
Furthermore Codeception allows for an easy generation of suites so this is legit

codecept generate:suite wpunit WPUnitTester
codecept generate:test wpunit AdminNotice
wpcept generate:wpunit wpunit ConflictingOptionAdminNotice

In the end unit, functional and acceptance suites are guidelines, not boundaries.