Functional Testing vs. Performance Testing and the Value of Using Both
Functional testing and performance testing are two types of software testing and quality assurance (QA) that enable developers and performance engineers to ensure the quality of their code. However, not all engineering teams implement testing when developing. This blog post will explain what functional testing and performance testing are, how they relate to each other and how they differ, and when you should choose each one. I will also include some tips about running each type of test.
I wrote this article mainly thinking about API testing, as APIs are what I generally work with, but most of the things mentioned here also apply if you run automated GUI tests.
What is Functional Testing?
A functional test asserts that a piece of software is functional, which means that it generates the desired output for a given input. These tests work on a list of inputs and associated desired outcomes so that they can produce a definite “pass” or “fail” signal. Functional tests are commonly used for regression testing as they can quickly verify that a change in the implementation did not break the overall software.
What is Performance Testing?
A performance test checks whether a software remains functional with increased demand and under various environmental conditions. It is a “functional test at scale”, as I like to call it. Different performance testing styles, such as load testing, stress testing, soak testing, and spike testing, specify the number of total users interacting with the software at a given time and define how this number changes over time.
The performance test doesn’t necessarily result in a definite “pass” or “fail”. The software might generate the right output but require an unacceptable amount of time to do so. In performance testing, you can evaluate your software based on various KPIs, including response times and error rates.
Creating Functional Tests
When you create functional tests, you generally start from basic tests and move on to advanced tests, from simple unit testing to advanced integration testing. In the most basic form, you test a simple interaction, i.e., you provide one input and expect one output. For example, you could give a calculator app the input “2+2” and assert that it returns “4”. Or you could load a website and assert that it contains a specific word. Once you’ve covered the basics, you can test chains of interactions. For example, you could test how a user registers for your website, logs in, adds a product to a shopping cart, and goes to the checkout page.
You can also use functional tests for negative testing, or fuzz testing. These tests verify that the software can handle invalid input. For example, you could try to divide by zero in the calculator, create an account with an already-registered email address on your website, or access information that the user is not allowed to see. These tests are beneficial for checking your software’s security requirements as well.
As functional tests are used for regression testing, they should either run on-demand - whenever a new version of the code is available, or on a regular schedule. Unless functional test design uses production datasets, you can reuse these tests in different environments and rely on them to prevent the deployment of non-functioning software. That said, it also makes sense to run them regularly in production to ensure that your environmental conditions don’t hinder any functionality.
Creating Performance Tests
Like functional tests, performance tests can also cover a single interaction, such as loading a website or making an API call, or scenarios with multiple steps. You can generally reuse functional tests as a performance test. But, you’re most likely to run fewer different tests in total or make them less complicated. The reason is that while it’s sufficient for a functional test to run at once, a performance test is all about running the same test scenario multiple times, both simultaneously or in quick succession. Hence, every test requires resources in both the system being tested and the infrastructure used for launching the tests.
Luckily, with cloud-based tools like BlazeMeter, you don’t have to worry about the latter, as you can reuse BlazeMeter’s servers in data centers from various cloud providers to make requests against your software or API.
Unlike functional tests, designing performance tests goes beyond defining what to test and what to expect. You also need to specify how many virtual users (VUs) you need and how you want them to behave, depending on whether you’re running a classic load test or, for example, a stress test.
Another question for creating performance tests is when, how often, and where you want them to run. You can run them whenever there’s a software update, on a regular schedule, or even in anticipation of specific events that could result in additional demand, which you want to make sure you can meet.
The tests also depend on the environment. Suppose you’re going to run them in a staging environment. In that case, this environment should resemble your production environment as closely as possible, so you can apply your test results from staging to production. If you want to run them directly in production, you need to be aware that they are also affected by the live traffic at the time and, conversely, tests like stress tests can affect your live performance. You can avoid that by scheduling at times with low demand, e.g., simulate a busy Monday on a slow Sunday.
Planning Tests in your Software Development Lifecycle
In the early stages of software development, functional tests generally take precedence over performance tests. With some development methodologies, such as TDD (test-driven development), developers create functional tests even before implementing the feature being tested. The focus on functional tests makes sense because it is pointless to test the performance of something that doesn’t work. I’m not an advocate for TDD, but testing shouldn’t be an afterthought either. Make sure to include negative tests for invalid input as well.
Still, it’s important to have performance testing on your mind. Your users have experienced your competitor’s software and they expect better performance from your web application or API. A few software teams only start thinking about performance testing after receiving negative user feedback. Don’t be one of them! Include these tests when you’re planning your project and start building them once you have completed your first performance-critical features, their functional tests, and their production infrastructure.
The Case for Building Functional Tests and Performance Tests
Looking at the differences between functional and performance tests, it becomes apparent that you need to assert both functional and non-functional requirements of your software. With functional tests, you can cover the basics and also add complex scenarios and negative testing on top. This ensures the security and integrity of your software. With performance tests, you can make sure that the common and crucial customer journeys remain available with an acceptable quality even when your software system experiences high demand.
Ready to get started with performance testing? Create your first test today.