Chronicles of a build - the signup plugin 07

Disclaimer

What I write in these posts is not the perfect travel of an expert and consumed WordPress developer but the gnarly and error-prone stroll of an average developer (pun intended).
I will make mistakes and will try to correct them along the road and mean to share the path I’ve taken with all its fallbacks and wrong turns and not to show the best possible one.

Follow along

After setting up the plugin using grunt-init I’ve deployed it in my local site and made it available on GitHub. I will commit to the GitHub repository throughout the work and the plugin can be downloaded and installed in WordPress. The code I show becomes much more comprehensible when observed in context.

Some small refactoring along the way

In my last post I had finally got the green light in the first Selenium test I had set up and the temptation is to move on, set up another test and go.
The reality is that passing this first test forced me to some design decisions but did not enforce any kind of implementation decisions like using an OOP approach to the plugin development.
Moving into unit-testing my code will require me to structure it to be testable and simple.

Making my plugin testable

When I first decided to adopt Test-driven Development I had to face a problem: TDD work better when the code is completely written using Object-oriented programming and WordPress is not.
The idea of unit-testing software components down to the single class level is to be able to mock all the objects the class or object is connected to and test that the object or class behaves, interacts and returns values or objects in the desired way.
The problem with writing TDD plugins, or themes, in WordPress lies in the fact that what needs to be mocked is not a single class most of the times but global functions and global variables.
I’d say three possible solutions exist:

  1. do not mock WordPress and instead have a bare-bones version of it run to create a full WordPress environment where you I can test my code with something like wordpress-tests
  2. mock global variables and functions using something like runkit
  3. isolate my code from WordPress using adapter classes, mock those classes and test my code with no frameworks.

List responsabilities

Before I try to isolate my code in an OO environement I break my classes into smaller classes to deal with classes that only have a single responsibility. I begin with the /includes/class-member_signup_admin.php file and parse it looking for responsabilities outlined by verbs. The idea is that classes shoulb be as specialist as they can get the same way I’d ask a mechanic to repair my car, a painter to paint it new and a car cleaner to clean it in place of asking someone to repair my car, paint it and clean it; parsing my code yelds I find that it:

constructs an instance of itself
gets an instance of itself
enqueues scripts
enqueues styles
adds a plugin menu
displays plugin menu
adds action links
registers settings
displays some markup (via some callback functions)
validates options  

I tried to express all the elements of the above list using action target couples and no clear pattern emerges: what is the single responsibility the main class of the admin side of my plugin has? All the above code is often found in WordPress plugin classes or main plugin file and I’m not pointing my finger and tell the good from the bad: if it works it’s good for me but in the context of TDD it’s a complication I want to get rid of.

Breaking down the class

Theory

Test-ability of a class to me means I can test what could go wrong and will break down the responsabilities of the class with two questions in mind:

  1. Do I want to test it?
  2. Can I test it?

This is the best graphical representation I can come up with of what I’m trying to do: to go fro this situation where I can test only “inner” classes of the plugin not dependant on any WordPress classes, functions and variables (in the below pictures green filled circles are testable) [caption id=“attachment_189” align=“aligncenter” width=“1024”]Not so OOP and not so testable Not so OOP and not so testable[/caption] To this situation where I can test all the classes my plugin is composed of aside for the adapter classes that are supposed to be so stupid in their logic, mainly wrapping methods, not to deserve or require any kind of test [caption id=“attachment_193” align=“aligncenter” width=“1024”]More OOP more testable More OOP more testable[/caption]