Beginners Guide to Testing in Symfony
In this video we are going to take our first look at testing inside a Symfony2 application.
Testing is a subject that is near and dear to my heart. I would go as far as to say that testing is like software development with cheats turned on.
Think about it - if you had the choice between writing some code that you think may work, versus writing some code that provably works - which would you choose to write?
What about if you had to do write some code that would be going on a production web site, one visited by hundreds of thousands of people per day? Would you want your code to work as expected, or are you content with throwing out a few hundred lines of guess work and letting your poor customers verify that it works?
Modern Development Practice === Testing
PHP used to be flaky.
Then things like Symfony, Composer, and PHPUnit came along.
Nowadays there really is no excuse to be throwing out untested garbage. And whilst there are many excuses for not doing so, I firmly believe the only real reason for developers not writing tests is that inherently, humans are lazy.
I'm going to show you how easy it is to get started writing tests inside a Symfony2 application. The good news - testing is built in.
The bad news? Well, testing this way is going to be 'testing the Symfony way'. And that's not an entirely transferrable skill.
Instead, it is better - in my opinion - to learn a generic testing setup, Codeception or Behat. Ideally both, but to begin with, Codeception is easier.
But Isn't Symfony Testing Done With PHPUnit?
That's the nice thing. PHPUnit is a separate, purpose built unit testing framework that Symfony, Codeception, and at the time of writing, 16,284 other projects depend on.
So, learning how to use PHPUnit is an entirely transferrable skill.
However, Symfony also comes with its own testing client and crawler. And outside of a Symfony project, you won't see these in use. This means learning a none-transferable set of skills, and also restricts your test code to only working in a Symfony project, unless you want to manually manage the dependencies.
To understand what the Symfony test client and crawler are doing, you must first understand the two (ahem) types of test available to us as developers.
If you read the Symfony best practice guide for Testing, you will immediately see they say there are two types of tests. Unit tests, and functional tests.
The variety of tests is initially confusing. I think that is part of the reason that testing is still not wholey adopted. I know I found this confusing to begin with. Let's look at the types of tests available to us:
Ad-hoc Testing / Manual Testing
Ahhh manual testing. What a crock.
This is when team members do a manual click > next > click > fill in box > click > save > check db, all looks good, let's get this bad boy in to production.
Of course, this feature will likely never, ever be tested again. Not unless another process that's being manually tested covers this work flow. It's impossible. No one has the time to sit and check and re-check their old code from every feature still works exactly as expected, remembering to cross reference that obscure DB flag is set when condition X occurs.
This doesn't work.
Please, for the love of all that is holy, don't fool yourself into believing that manual testing is testing.
The first step to salvation.
Unit testing involves writing more PHP code to automatically and repeatably prove that the methods / functions you have written behave as expected.
This can involve sending in some good values and seeing the expected results, and also sending in bad values and that your methods handle them in a predictable manner.
As the name implies, PHPUnit is all about Unit testing. There is also PHPSpec which offers a different approach to solving the same problem.
Functional testing involves writing more PHP code to automatically and repeatably prove that the methods / functions you have written behave as expected.
Isn't that exactly like Unit Testing?
Yes! Except this time we are testing that a larger part of the system works as expected.
Lets imagine we have three (unit tested) classes that interact together to produce a desired outcome on our website.
Our unit tests ensure that the classes behave properly in isolation.
Our functional tests ensure that our classes behave properly when working together.
All of this is done from a code perspective - that is, we never have to open a real web browser to prove this behaves properly.
This is where Symfony's test client primarily comes in to play. And this is where I would advise you instead start using a dedicated testing tool like Codeception or Behat.
Acceptance testing involves writing more PHP code to automatically and repeatably prove that the methods / functions you have written behave as expected.
I'm sure you are detecting a pattern here.
The difference between Functional and Acceptance testing is that where Functional testing never uses a real web browser, Acceptance testing will fire up a real browser and check the real web page behaves as a real user would experience it.
Codeception and Behat make this kind of testing incredibly easy, and being able to reliably reproduce a work flow as though a real life human being were sat at a computer, entering data both rightly and wrongly, and then (hopefully) seeing the expected outcome either way is incredibly powerful.
Acceptance testing also greatly increases managerial confidence in the system and the team. It's efficient, automated, repeatable and awesome. Why aren't you using this again?!
Other Types of Tests
There's a whole raft of other test names which you will likely start to hear.
Black box testing, white box testing, integration testing, regression testing, smoke testing... the list goes on... and on, and on!
Simply, most of them are covered by Unit, Functional, and Acceptance testing.
If you are curious to find a likely non-exhaustive list, this website is a great reference.
Where Should I Begin?
Begin by watching the video :)
You will see how testing inside Symfony is easy enough to get going.
Once you have seen how easy it is to write a few tests, you will also hopefully see how much of time saver and a confidence booster this can become.
From there, switching to Codeception or Behat is a matter of personal preference. See which one looks easier to learn, and then get learning.
Testing will improve your life in many ways. Your code will become cleaner. Your tests serve as great documentation. And at 5pm on a Friday you can re-run the tests, see all is green, and then head to the pub, safe in the knowledge that you didn't break the system. If that's not reason enough, I don't know what is!