Symfony 2.8 Jobeet Day 9: The Functional Tests
Functional tests are a great tool to test your application from end to end: from the request made by a browser to the response sent by the server. They test all the layers of an application: the routing, the model, the actions, and the templates. They are very similar to what you probably already do manually: each time you add or modify an action, you need to go to the browser and check that everything works as expected by clicking on links and checking elements on the rendered page. In other words, you run a scenario corresponding to the use case you have just implemented.
As the process is manual, it is tedious and error prone. Each time you change something in your code, you must step through all the scenarios to ensure that you did not break something. That’s insane. Functional tests in Symfony provide a way to easily describe scenarios. Each scenario can then be played automatically over and over again by simulating the experience a user has in a browser. Like unit tests, they give you the confidence to code in peace.
Functional tests have a very specific workflow:
- Make a request;
- Test the response;
- Click on a link or submit a form;
- Test the response;
- Rinse and repeat.
Our First Functional Test
Functional tests are simple PHP files that typically live in the
Tests/Controller directory of your bundle. If you want to test the pages handled by your
CategoryController class, start by creating a new
CategoryControllerTest.php file that extends a special
Running Functional Tests
As for unit tests, launching functional tests can be done by executing the
phpunit -c app/ src/AppBundle/Tests/Controller/CategoryControllerTest
Writing Functional Tests
Writing functional tests is like playing a scenario in a browser. We already have written all the scenarios we need to test as part of the day 2 stories.
Expired jobs are not listed
First, let’s test the Jobeet homepage by editing the JobControllerTest.php test file. Replace the code with the following one:
To verify the exclusion of expired jobs from the homepage, we check that the CSS selector
.jobs td.position:contains("Expired") does not match anywhere in the response HTML content (remember that in the fixtures, the only expired job we have contains “Expired” in the position).
Only n jobs are listed for a category
Add the following code at the end of the test file. To get the custom parameter defined in
app/config/config.yml in our functional test, we will use the kernel:
For this test to work we will need to add the corresponding CSS class to each category in the
job/index.html.twig file (so we can select each category and count the jobs listed):
A category has a link to the category page only if too many jobs
In these tests, we check that there is no “more jobs” link for the design category (
.category_design .more_jobs does not exist), and that there is a “more jobs” link for the programming category (
.category_programming .more_jobs does exist).
Jobs are sorted by date
To test if jobs are actually sorted by date, we need to check that the first job listed on the homepage is the one we expect. This can be done by checking that the URL contains the expected primary key. As the primary key can change between runs, we need to get the Doctrine object from the database first.
Even if the test works as is, we need to refactor the code a bit, as getting the first job of the programming category can be reused elsewhere in our tests. We won’t move the code to the Model layer as the code is test specific. Instead, we will move the code to the
getMostRecentProgrammingJob function in our test class:
You can now replace the previous test code by the following one:
Each job on the homepage is clickable
To test the job link on the homepage, we simulate a click on the “Web Developer” text. As there are many of them on the page, we have explicitly to ask the browser to click on the first one.
Each request parameter is then tested to ensure that the routing has done its job correctly.
Learn by the Example
In this section, you have all the code needed to test the job and category pages. Read the code carefully as you may learn some new neat tricks:
That’s all for now. Get the code from today: https://github.com/dragosholban/jobeet-sf2.8/tree/day9