Why Test?
Testing code really isn’t about proving that something works, it’s purpose is to really make sure that in the future it still works after the system changes. Sure, no-one’s perfect but in general engineers write good code that’s mostly bug-free. Attention to detail is one quality that every engineer needs, so they test their code as they go, but it’s usually not in a way that can be automated.
Bugs at least in my experience are introduced as a consequence of a change elsewhere in the system. Large software systems have many moving components, sometimes to a point where the entire system design can’t really fit into your mindspace. A change in one service can/will affect all other systems that use that service. This is where bugs are born. Most developers are unaware of the downstream or upstream impacts of such changes, which is why testing is incredibly important in any large application.
Unit Testing
Unit Testing is a technique of software testing where individual units/ components of a software are tested. The purpose is to validate that each unit of the software performs as required. Ideally, a unit is the smallest testable part and it usually has a few inputs and a single output (in most cases). Any external dependency should be “Mocked” and provided to maintain control. Dependencies are a form of Input/Output which is just as important than the data coming in and out. Making sure the Unit Test covers all possibilities is a sure-fire way of preventing bugs. Reducing complexity via other methods aide greatly in reducing the amount of effort required to properly Unit Test.
Integration Testing
Integration Testing is a technique of software testing where units are tested as a whole. The purpose of this testing is to prove that there are no faults in the interaction between integrated units. These tests are important to expose new potential faults in new units that may be added to the group and exposes any failure that the change introduces. While testing at a unit level will expose simple logical errors in the unit, integration tests show logical errors, integration tests expose faults in interfaces between units.
Analogy
During the process of producing a pen; the components like the tip, cap, ink, are all produced separately and tested separately. When a couple of components are ready like the tip and cap, they are assembled and integration testing is performed. If the Tip is too big for the cap, for instance.
End to End Testing
End to End Testing is a technique to testing many components as a whole. The purpose of the system test is to ensure the entire system functions as designed. If I do X does A,B,C happen style of testing. The goal of this type of test is to ensure that a change does not wildly affect different systems and also serves as an excellent form of documentation, as does the other testing techniques.