To explain why software testing is important, we’ll start with an example. How would you answer if we asked you to drive a car that nobody has ever tested in a Formula 1 race? Would you risk your life with something nobody has ever checked to see if it’s robust enough to not get destroyed at the first curve? Or that the brakes actually brake the car? Of course, the answer to all these questions is a big “No!” The same principle applies to software. Nobody wants to use software that crashes every two minutes or that doesn’t work as expected, or even worse, that doesn’t match the requirements or the expectations of the user. That’s exactly where software testing comes into play.
Software testing is the process of evaluating a piece of software to detect differences between the actual and expected output, with a given input. Testing helps build safe, reliable, and stable software. It provides valuable information and insight into the state of the system or software. Software testing also serves as a metric of how your product differs from the specifications, customer expectations, past versions of the same product, and many other criteria. Another primary purpose is to detect defects of the code, usually referred to as bugs.
When talking about bug detection, we don’t mean that testing allows you to verify all the possible conditions and find every bug in your system, which is impossible in every real-world system. The scope is to verify your code, product, or system under certain conditions to see if it works as expected. Even employing testing, bugs will always exist. This isn’t something you can eradicate with practice or knowledge because it’s intrinsic in every complex system. You have to accept that bugs in software exist not because you or other developers working on it aren’t good enough, but because any real-world software is so complex that you can’t predict, and thus fix, every source of failure.
Testing is an essential part of the life of every developer. At least, it should be. Unfortunately, many developers are scared of testing. It’s often seen as an extra activity, something that forces you to waste time—a lot of time. Of course, you don’t have to take this wisdom to the other extreme. If you’re developing a really small piece of code for yourself to automate a process you only have to perform once in your life, testing it is probably not worth the effort. But as more experienced developers will confirm, if you’re developing even a small project or library that you plan to use in your daily work and share with your team, other developers, or the entire JavaScript community, then you’d better test it.
Testing is an incredibly wide discipline. You can test your projects for a bunch of different aspects (for example, compatibility testing and regression testing), using different methods (for example, visual testing and black-box testing), and at different levels (for example, unit testing and integration testing). By no means is the purpose of this section to teach you the ins and outs of software testing. The topic is so broad that it would require us to write another app just for this topic. What we want to communicate here is the importance of testing and why you should test your software in case you haven’t been doing it yet.
In the next section, we’ll give you an overview of one of the types we mentioned: unit testing.
Why unit testing?
Unit testing is a software testing method that promotes the practice of thinking of software as a set of isolated pieces of code, referred to as units, that can be tested individually to verify that they work as expected. When unit testing, each set of tests targeting a single unit should be independent from the others. Usually a unit is identified by a function or a method, depending on the type of programming language adopted.
In short, the main benefits of unit testing code are these:
- Attest that the code returns expected results given specific inputs.
- Discover the highest number of defects in an early stage (related to the previous point).
- Improve the design of the code.
- Identify units that are too complex.
Adhering to the principles of unit testing, given a function of your software and a set of inputs, you can determine if the function is returning the expected outputs. This process is usually automated and involves a unit-testing framework. Unit testing consists of writing functions that, when executed, pass a set of inputs you’ve defined to the targeted function (the one you’re testing). Then these functions verify that for each set of inputs the returned result is the one expected (that you’ve defined in the test function). Employing this method, you can also verify that if you pass invalid inputs to the targeted function, the latter is able to deal with them gracefully (this can also mean raising an expected error or exception). When one or more tests fail, you know there’s an error in the code of the unit, so you need to fix it. This process is iterated until all the tests are passed (the results returned match those expected).
The goal of unit testing is to find the largest percentage possible of software defects in an early stage of the development process. Another advantage is that once you have all the tests for a given unit in place, you can improve the code of the unit (function or method) confidently. If you make a mistake while updating the code, one or more tests will (usually) fail and you’ll know that something went wrong. Therefore, you can change your code more confidently knowing that you’re not breaking a feature that used to work properly.
Another benefit always associated with unit testing is that it helps in understanding and improving how to design the code. Instead of writing code to do something, you start by outlining all the conditions your code has to meet and what outputs you expect. This concept is usually related to a development methodology called test-driven development (TDD).
Test-driven development
Test-driven development is a software development process that relies on writing tests before writing the code (unit) to test. The first step in TDD is to write an initially failing test case. Then the developer has to produce the code that implements the feature until all the tests are passed. Finally, the code is refactored until it matches an acceptable quality standard.
The final advantage we want to highlight is that unit testing helps in identifying units that are too complex. For example, you can recognize that a method is doing more than its primary goal—remember the single responsibility principle (SRP). What usually happens is that when writing the test code you feel that it’s too complex or it’s becoming too long. This is a good indication that the method needs to be divided up or refactored.
If a project is developed with JavaScript, there’s an additional reason to embrace testing: browser incompatibilities. Although the major browsers, including Internet Explorer, are adhering to web standards more and more every day, they still have different behaviors in many circumstances. Having solid tests is one way to avoid the issue of deploying code that works in certain browsers and breaks your web pages in others. You can run the same tests in different browsers to verify that all of them pass.
Now that you have an idea of what testing and unit testing are, and you have a good grasp of why you should employ them, it’s time to take a look at the unit-testing frameworks available for your JavaScript code.
Leave a Reply