Types of tests

While writing your application, making changes to the existing code, or adding new features, it is very important to get good feedback. How do you know that the feedback you get is good enough? It should accomplish the AEIOU principles:

  • Automatic: Getting the feedback should be as painless as possible. Getting it by running just one command is always preferable to having to test your application manually.
  • Extensive: We should be able to cover as many use cases as possible, including edge cases that are difficult to foresee when writing code.
  • Immediate: You should get it as soon as possible. This means that the feedback that you get just after introducing a change is way better than the feedback that you get after your code is in production.
  • Open: The results should be transparent, and also, the tests should give us insight to other developers as to how to integrate or operate with the code.
  • Useful: It should answer questions such as "Will this change work?", "Will it break the application unexpectedly?", or "Is there any edge case that does not work properly?".

So, even though the concept is quite weird at the beginning, the best way to test your code is… with more code. Exactly! We will write code with the goal of testing the code of our application. Why? Well, it is the best way we know to satisfy all the AEIU principles, and it has the following advantages:

  • We can execute the tests by just running one command from our command line or even from our favorite IDE. There is no need to manually test your application via a browser continually.
  • We need to write the test just once. At the beginning, it may be a bit painful, but once the code is written, you will not need to repeat it again and again. This means that after some work, we will be able to test every single case effortlessly. If we had to test it manually, along with all the use cases and edge cases, it would be a nightmare.
  • You do not need to have the whole application working in order to know whether your code works. Imagine that you are writing your router: in order to know whether it works, you will have to wait until your application works in a browser. Instead, you can write your tests and run them as soon as you finish your class.
  • When writing your tests, you will be provided with feedback on what is failing. This is very useful to know when a specific function of the router does not work and the reason for the failure, which is better than getting a 500 error on our browser.

We hope that by now we have sold you on the idea that writing tests is indispensable. This was the easy part, though. The problem is that we know several different approaches. Do we write tests that test the entire application or tests that test specific parts? Do we isolate the tested area from the rest? Do we want to interact with the database or with other external resources while testing? Depending on your answers, you will decide on which type of tests you want to write. Let's discuss the three main approaches that developers agree with:

  • Unit tests: These are tests that have a very focused scope. Their aim is to test a single class or method, isolating them from the rest of code. Take your domain class as an example: it has some logic regarding the addition of books, right? A unit test might just instantiate a new sale, add books to the object, and verify that the array of books is valid. Unit tests are super fast due to their reduced scope, so you can have several different scenarios of the same functionality easily, covering all the edge cases you can imagine. They are also isolated, which means that we will not care too much about how all the pieces of our application are integrated. Instead, we will make sure that each piece works perfectly fine.
  • Integration tests: These are tests with a wider scope. Their aim is to verify that all the pieces of your application work together, so their scope is not limited to a class or function but rather includes a set of classes or the whole application. There is still some isolation in case we do not want to use a real database or depend on some other external web service. An example in our application would be to simulate a object, send it to the router, and verify that the response is as expected.
  • Acceptance tests: These are tests with an even wider scope. They try to test a whole functionality from the user's point of view. In web applications, this means that we can launch a browser and simulate the clicks that the user would make, asserting the response in the browser each time. And yes, all of this through code! These tests are slower to run, as you can imagine, because their scope is larger and working with a browser slows them down quite a lot too.

So, with all these types of tests, which one should you write? The answer is all of them. The trick is to know when and how many of each type you should write. One good approach is to write a lot of unit tests, covering absolutely everything in your code, then writing fewer integration tests to make sure that all the components of your application work together, and finally writing acceptance tests but testing only the main flows of your application. The following test pyramid represents this idea:

Types of tests

The reason is simple: your real feedback will come from your unit tests. They will tell you if you messed up something with your changes as soon as you finish writing them because executing unit tests is easy and fast. Once you know that all your classes and functions behave as expected, you need to verify that they can work together. However, for this, you do not need to test all the edge cases again; you already did this when writing unit tests. Here, you need to write just a few integration tests that confirm that all the pieces communicate properly. Finally, to make sure that not only that the code works but also the user experience is the desired one, we will write acceptance tests that emulate a user going through the different views. Here, tests are very slow and only possible once the flow is complete, so the feedback comes later. We will add acceptance tests to make sure that the main flows work, but we do not need to test every single scenario as we already did this with integration and unit tests.

Learning PHP 7
titlepage.xhtml
part0000.html
part0001.html
part0002.html
part0003.html
part0004.html
part0005.html
part0006.html
part0007_split_000.html
part0007_split_001.html
part0007_split_002.html
part0008_split_000.html
part0008_split_001.html
part0009.html
part0010.html
part0011.html
part0012.html
part0013_split_000.html
part0013_split_001.html
part0013_split_002.html
part0013_split_003.html
part0013_split_004.html
part0014_split_000.html
part0014_split_001.html
part0014_split_002.html
part0014_split_003.html
part0014_split_004.html
part0015_split_000.html
part0015_split_001.html
part0015_split_002.html
part0015_split_003.html
part0015_split_004.html
part0016_split_000.html
part0016_split_001.html
part0016_split_002.html
part0016_split_003.html
part0016_split_004.html
part0017_split_000.html
part0017_split_001.html
part0017_split_002.html
part0017_split_003.html
part0018.html
part0019_split_000.html
part0019_split_001.html
part0019_split_002.html
part0019_split_003.html
part0019_split_004.html
part0020_split_000.html
part0020_split_001.html
part0021_split_000.html
part0021_split_001.html
part0021_split_002.html
part0021_split_003.html
part0022.html
part0023_split_000.html
part0023_split_001.html
part0024_split_000.html
part0024_split_001.html
part0025_split_000.html
part0025_split_001.html
part0025_split_002.html
part0025_split_003.html
part0025_split_004.html
part0025_split_005.html
part0025_split_006.html
part0026.html
part0027_split_000.html
part0027_split_001.html
part0027_split_002.html
part0027_split_003.html
part0027_split_004.html
part0027_split_005.html
part0027_split_006.html
part0027_split_007.html
part0028_split_000.html
part0028_split_001.html
part0028_split_002.html
part0028_split_003.html
part0028_split_004.html
part0029_split_000.html
part0029_split_001.html
part0029_split_002.html
part0029_split_003.html
part0030_split_000.html
part0030_split_001.html
part0030_split_002.html
part0030_split_003.html
part0030_split_004.html
part0031_split_000.html
part0031_split_001.html
part0031_split_002.html
part0031_split_003.html
part0032.html
part0033_split_000.html
part0033_split_001.html
part0033_split_002.html
part0033_split_003.html
part0033_split_004.html
part0033_split_005.html
part0034_split_000.html
part0034_split_001.html
part0035.html
part0036.html
part0037_split_000.html
part0037_split_001.html
part0037_split_002.html
part0038_split_000.html
part0038_split_001.html
part0038_split_002.html
part0038_split_003.html
part0039_split_000.html
part0039_split_001.html
part0040.html
part0041_split_000.html
part0041_split_001.html
part0041_split_002.html
part0041_split_003.html
part0042_split_000.html
part0042_split_001.html
part0042_split_002.html
part0043.html
part0044.html
part0045_split_000.html
part0045_split_001.html
part0045_split_002.html
part0046_split_000.html
part0046_split_001.html
part0046_split_002.html
part0046_split_003.html
part0047_split_000.html
part0047_split_001.html
part0047_split_002.html
part0047_split_003.html
part0047_split_004.html
part0048.html
part0049.html
part0050_split_000.html
part0050_split_001.html
part0050_split_002.html
part0050_split_003.html
part0051.html
part0052.html
part0053_split_000.html
part0053_split_001.html
part0053_split_002.html
part0053_split_003.html
part0054.html
part0055.html
part0056_split_000.html
part0056_split_001.html
part0057_split_000.html
part0057_split_001.html
part0057_split_002.html
part0057_split_003.html
part0057_split_004.html
part0058_split_000.html
part0058_split_001.html
part0058_split_002.html
part0058_split_003.html
part0058_split_004.html
part0059_split_000.html
part0059_split_001.html
part0059_split_002.html
part0059_split_003.html
part0060_split_000.html
part0060_split_001.html
part0060_split_002.html
part0060_split_003.html
part0060_split_004.html
part0060_split_005.html
part0060_split_006.html
part0060_split_007.html
part0061_split_000.html
part0061_split_001.html
part0061_split_002.html
part0061_split_003.html
part0061_split_004.html
part0061_split_005.html
part0062_split_000.html
part0062_split_001.html
part0062_split_002.html
part0063.html
part0064_split_000.html
part0064_split_001.html
part0064_split_002.html
part0064_split_003.html
part0065_split_000.html
part0065_split_001.html
part0065_split_002.html
part0065_split_003.html
part0066_split_000.html
part0066_split_001.html
part0066_split_002.html
part0066_split_003.html
part0066_split_004.html
part0067_split_000.html
part0067_split_001.html
part0067_split_002.html
part0067_split_003.html
part0068.html
part0069_split_000.html
part0069_split_001.html
part0070.html
part0071_split_000.html
part0071_split_001.html
part0071_split_002.html
part0071_split_003.html
part0072_split_000.html
part0072_split_001.html
part0072_split_002.html
part0072_split_003.html
part0072_split_004.html
part0073_split_000.html
part0073_split_001.html
part0073_split_002.html
part0074_split_000.html
part0074_split_001.html
part0074_split_002.html
part0074_split_003.html
part0075_split_000.html
part0075_split_001.html
part0075_split_002.html
part0075_split_003.html
part0075_split_004.html
part0075_split_005.html
part0075_split_006.html
part0075_split_007.html
part0076_split_000.html
part0076_split_001.html
part0076_split_002.html
part0076_split_003.html
part0076_split_004.html
part0077.html
part0078.html
part0079_split_000.html
part0079_split_001.html
part0080.html
part0081_split_000.html
part0081_split_001.html
part0081_split_002.html
part0081_split_003.html
part0082_split_000.html
part0082_split_001.html
part0082_split_002.html
part0082_split_003.html
part0082_split_004.html
part0083_split_000.html
part0083_split_001.html
part0083_split_002.html
part0084_split_000.html
part0084_split_001.html
part0084_split_002.html
part0084_split_003.html
part0084_split_004.html
part0084_split_005.html
part0085_split_000.html
part0085_split_001.html
part0085_split_002.html
part0085_split_003.html
part0085_split_004.html
part0085_split_005.html
part0086.html
part0087.html
part0088_split_000.html
part0088_split_001.html
part0088_split_002.html
part0088_split_003.html
part0088_split_004.html
part0088_split_005.html
part0089_split_000.html
part0089_split_001.html
part0089_split_002.html
part0089_split_003.html
part0089_split_004.html
part0090_split_000.html
part0090_split_001.html
part0090_split_002.html
part0090_split_003.html
part0091.html
part0092_split_000.html
part0092_split_001.html
part0092_split_002.html
part0092_split_003.html
part0092_split_004.html
part0092_split_005.html
part0092_split_006.html
part0092_split_007.html
part0092_split_008.html
part0092_split_009.html
part0092_split_010.html
part0092_split_011.html
part0092_split_012.html
part0092_split_013.html
part0092_split_014.html
part0092_split_015.html
part0092_split_016.html
part0092_split_017.html
part0092_split_018.html
part0092_split_019.html
part0092_split_020.html
part0092_split_021.html
part0092_split_022.html
part0092_split_023.html
part0092_split_024.html