Software development often follows a familiar pattern: there's a relatively simple problem, and a program is written to solve it. Over time, additional situations arise that require extending the program, or changing how it behaves in certain conditions. Before you know it, that simple program has become frighteningly complex.
Knowing that the software lifecycle tends towards complexity, how do you ensure that a program continues to function correctly? If you add a feature, can you guarantee it won't break an existing feature? If you change something, will you have to worry about it having unforeseen effects on other subsystems? Quality Assurance is the general answer to all of these questions, and automated testing is an important component of QA.
We build tests that exercise an application so we can verify that it is behaving as expected. These tests operate on several different levels: unit tests, which test the underlying logic of code components, and functional tests, which simulate use of the applications. If we change any aspect of a project – the name of a function, a block of code, or even an underlying library – the tests will assure us that the application continues to function as expected (or we will be shown exactly what changed). This gives us the confidence to continue to enhance a project, and to add or change features.
Technically speaking, we use Selenium and Karma to test on the browser side, and PHPUnit for testing on the code side. We have a Jenkins continuous integration server, which runs all tests nightly.