4.2 Functional Tests
Now let's examine another type of test—functional tests—using the Codeception framework. Functional tests will allow us to test our entire application.
1.Introduction3 lessons, 05:32
2.Testing Methodologies3 lessons, 24:26
3.PHP Testing Frameworks3 lessons, 08:25
4.Test Types3 lessons, 36:05
5.Conclusion1 lesson, 00:36
4.2 Functional Tests
in the last lesson, we learned how to write unit tests, to test the unit of code within our application using the PHP unit framework. In this lesson, we'll learn how to write functional tests using the Codeception framework. Let's first define what a functional test is. A functional test is a way of testing that our PHP web application meets its functional requirements. So, now you may be wondering, why write functional tests if we've already wrote unit tests for our application? Well, the answer is that unit tests only test the features of our application as single units, and that's fine to ensure that those individual pieces of code work. But since we're programming in PHP, we're likely building a web application, and web applications need to be tested as an entire application with everything tied together, not just as single units. This is where functional tests shine in being able to test that an entire user experience works, such as testing a whole complex process of a user visiting a web page to fill out a registration form, clicking the submit button, and then being redirected to another page after being automatically logged in. Testing an entire user experience like this is possible using functional tests in Codeception, but demonstrating all of that code would take entirely too long. We just want to learn the basics of functional testing and to see it in action, right? Instead, we're going to write functional tests based around a much smaller user experience. We'll test that a user can visit our home page, click a link and end up on our about page. Now, functional tests work by emulating your application's behavior from within the test. Codeception handles setting the appropriate super globals, running your app, and etc., and then providing you with the test results based on the output Codeception received from your application. Functional tests are very similar to acceptance tests, as we'll see in the next lesson. The advantage functional tests have over acceptance tests is that they are quicker and don't require a web server to execute, unless you're using the PHP browser module as we will be in this lesson. Functional tests are also a little less stable. They are best written for parts of your app that are already considered to be stable code. If you have some complex logic in other parts you may want to consider acceptance testing for those. All right, here I am in Sublime. So, you should already have Codeception installed. If not, please review the Codeception framework lesson and then come back here when you're ready. So, you may notice that I removed that Tests folder with the capital T for our unit tests that we wrote in the last lesson, as not to distract you with too many other files floating about. Now if you haven't done so, please make sure that you've bootstrapped your Codeception installation to your phptestingbasics application. You'll know if you've done this, if after following the Codeception lesson of this course, you should have this tests folder with a lowercase t. And this is different than the Tests folder that we created in the last lesson for the unit tests, that one had a capital T. Now, if you look inside of this test folder, you'll see that we have a variety of files and folders. We're only going to be concerned with the functional folder and the functionalsuite.yml file here. Let's open up this functionalsuite.yml file. Now in order to properly test our application, we need to use a special module called PhpBrowser, that's not used by default in functional tests. By enabling this module, we'll gain access to a lot of cool testing features. So, let's add it into this enabled array here. There we go, you can see I've added the PhpBrowser module here to the enabled list. After the enabled list, we also need to set up the URL config option for it. It would look something like this. All right, there we go. You can see I'm setting the config for the PhpBrowser module. We're just setting the application URL for it. We're pointing it to http://localhost:8000/. Now, make sure that your server is running before attempting to run your tests later on. Otherwise, you're going to get an error. So, I'm just going to switch into my terminal to start up my server now, just so I won't forget. Make sure you're inside of the phptestingbasics folder, and we can start up our server by running php -S, localhost:8000. All right, I'm back in Sublime. Now, any time you modify one of your suite config files, like we've done here for our functional config file, you have to rebuild the TestGuy class, which you'll learn about in just a moment. You need to rebuild that file so that your tests will run properly and use the appropriate modules that you've enabled. So, I'm going to switch back into my terminal and let's run the following command, php, vendor/bin/codecept build. There we go, our TestGuy has been rebuilt. Let's now move on and take a look at the functional folder. I'll switch back into Sublime, and inside of tests, let's open up the functional folder. So you can see here, we have this _bootstrap.php file. You can use this for initializing code that you may want access to from within your tests. I'll just close this out. And you'll also notice a file named TestGuy.php. Now, you don't wanna mess around and this one, this is TestGuy, the file I was talking about earlier, that we rebuilt when we added in the PhpBrowser module. TestGuy is one of the classes within Codeception that handles running your functional tests. All of the different kinds of tests that Codeception can run, have a different guy. So, feel free to browse around the other folders to take a look. I'm just going to close this out and we can also close out our functional config file as well. Now to begin writing functional tests, we just need to generate our test file. I'm going to switch back into my terminal, and let's run the following command, php vendor/bin/codecept generate:cept functional. Now we just need to give our functional test a name. I like to be descriptive about the process or the behavior that I'm testing. Since here, we're really just testing the process of being able to navigate through our site by clicking links, I'll just call this SiteNavigation. There we go, that creates our SiteNavigationCept.php file, our test file. Let's go back into Sublime, and under functional, you should see our test file here. Let's open it up. Now by default, Codeception hopefully inserts a new instance of our TestGuy, and it gives our functional test this little generic description, so we can now use this I object to test the functional requirements of navigating through our site. First, let's just update the description here. I'll change it out. Let's have this say, I want to ensure we can visit the about page from the home page. Now let's write our first test. We can begin by asserting that we're on our home page, which would be index.html, by calling the amOnPage method. We can simply pass in a URI for the page that we want to test that we're on. So, let's use our I object. We'll call the amOnPage method, and we'll test that we're on the index.html page, our home page. Now let's make sure that the user can click on an About link. We can do this by calling a click method and passing in the name of the link to be clicked. Let's use our I object and we'll call the click method, and we'll ensure that we can click on an About link. Next, we need to make sure after clicking the link, that we're now on the about page. We can make sure that we're on the proper page by checking for elements that you know should be on that page. We can do that by using the see method. We first pass in the content that we expect to see, and then the second argument is the html element, itself, that you expect the content to be in. So, let's make sure that we see some text saying, About Functional Tests, and that it's within an Hh heading element. So, let's use our I object, we'll call the see method. We expect to see some text saying, About Functional Tests, and it should be within an h1 heading. Perfect. We've now quickly written out three lines of code which test out quite a bit of functionality. Let's now run our tests. I'll switch back into my terminal,. Now make sure you are within your phptestingbasics folder and we can run the following command to execute our functional tests. We'll run php vendor/bin/codecept run functional. And after running our test, we can see that it has indeed failed. We have a message here saying, failed to ensure we can visit the about page from the home page. You can see that it says, sorry, I couldn't click About. Basically, our test is failing because we don't have a home page with a link to visit the about page, which also doesn't exist. So, let's go ahead and fix this to get our test passing. I'll switch back into Sublime. Let's close up the tests folder, and within the phptestingbasics folder inside the root of it, let's create a new file and I'll save this as index.html. And we'll keep this really simple. Remember, we only want to write enough just to get the test to pass. So, let's start by creating a heading. There we go. We have our heading of Testing Home Page. Let's also create a paragraph here with a link, linking to the About page, about.html. This'll just say About with a capital A, and then after that let's put in a little content for the body of the page, just to make it look a little better. Okay, here's our home page. Now let's create our about page. Again within the root of the phptestingbasics folder, I'll create a new file. I'll save this as about.html. Now to get our test to pass our about page requires that we have an h1 heading saying About Functional Tests. So, let's create that heading now. And again, I'll also add in a little bit of text for the body, just to fill in the page. All right, that's it. Our application has now been written according to our functional requirements. Let's rerun our test. I'll switch back into the terminal and let's rerun that command codecept run functional. And perfect. This time our test passed. We now know that our application site navigation, at least up to the current requirements, work as intended. The tests are even readable and even the output here is perfectly presentable to non-programmers. Next up, we'll review the last test type, acceptance tests, using the Behat framework. This will be a dual lesson as we'll also be focusing on BDD principles. So, I'll see you there.