8 Functional Testing Types Explained With Examples
In software testing, functional testing is a practice that delivers huge benefits to the development process. When done properly, it increases communication between analysts, developers, and testers. The progress of the entire project is objectively visible at any point in time to management by examining the passing (and failing) functional tests. Eventually, the speed of development increases because well-communicated requirements result in less re-work. The tests also drive a more modular architecture with subsystems that have clear responsibilities.
This blog specifies the scope of different types of functional testing, their importance, and when to perform them. For example, smoke testing is performed on each build delivered to QA because it verifies the functionality at a high level while regression testing is performed when bugs are fixed in subsequent releases.
Different Types of Functional Testing
Unit testing ensures that each part of the code developed in a component delivers the desired output. In unit testing, developers only look at the interface and the specification for a component. It provides documentation of code development as each unit of the code is thoroughly tested standalone before progressing to another unit.
Unit tests support functional tests by exercising the code that is most likely to break. If you use functional tests without unit tests, you may experience several smells:
- It’s hard to diagnose failed tests
- Test fixtures work around known issues rather than diagnosing and fixing them
Testing a module or component independently to verify its expected output is called component testing. Generally, component testing is done to verify the functionality and/or usability of a component but not restricted to only these. A component can be of anything which can take input(s) and delivers some output. For example, the module of code, web page, screens and even a system inside a bigger system is a component to it.
From the above picture, Let’s see what all we can test in component 1 (login) separately:
- Testing the UI part for usability and accessibility
- Testing the Page loading to ensure performance
- Trying SQL injection through the UI components to ensure security
- Testing the login functionality with valid and invalid user credentials
Smoke testing is performed on the ‘new’ build given by developers to QA team to verify if the basic functionalities are working or not. It is one of the important functional testing types. This should be the first test to be done on any new build. In smoke testing, the test cases chosen cover the most important functionality or component of the system. The objective is not to perform exhaustive testing, but to verify that the critical functionality of the system is working fine.
If the build passes the smoke testing then it is considered as a stable build. On the stable build, QA team performs functional testing for the newly added features/functionality and then performs regression testing depending upon the situation. But if the build is not stable i.e. the smoke testing fails then the build is rejected and forwarded to the development team to fix the build issues and create a new build. Let’s understand it better with an example.
We’ve built an Employee portal application for our client. As we follow continuous testing we had to test each build right after its development. The client wanted us to build the portal which consists of features like leave application, leave reports, store employees’ data, etc.
First, developers build a leave application feature and passed to QA for testing. The QA team examined that the entire build required 80-100 test cases for all the scenarios:
- Show total leaves count and types
- Testing of the calendar while selecting the date
- Select date
- User should be able to fill the required information. i.e., a reason of the leave
- After applying request sent to the manager for approval
- Manager approves the leave
- Employee gets notified
- Leave gets deducted from the total count
Here smoke testing comes in picture. Instead of testing all the functionalities, they decided to test only critical functionalities which had only 20 test cases. These test cases covered the following scenarios:
- Select date
- Fill other details
- Request sent to the manager after clicking the button
As you can see we have taken only the main features for testing which were critical. For example, if an employee can’t select the date then there’s no need for further testing. This saves the developers’ time of fixing bugs.
Integration testing is performed to test individual components to check how they function together. In other words, it is performed to test the modules which are working fine individually and do not show bugs when integrated. It is the most common functional testing type and performed as automated testing.
Generally, developers build different modules of the system/software simultaneously and don’t focus on others. They perform extensive black and white box functional verification, commonly known as unit tests, on the individual modules. Integration tests cause data and operational commands to flow between modules which means that they have to act as parts of a whole system rather than individual components. This typically uncovers issues with UI operations, data formats, operation timing, API calls, and database access and user interface operation.
Let’s take an example of another project of search functionality in the e-commerce site where it shows the results based on the text entered by users. The complete search function works when developers build the following four modules.
Module #1: This is the search box visible to users where they can enter text and click the search button.
Module #2: It’s a converter or in simple terms program which converts entered text into XML.
Module #3: This is called Engine module which sends XML data to the database.
Module #4: Database
In our scenario, the data entered in the search function (module #1) gets converted into XML by module #2. The EN module(module #3) reads the resultant XML file generated by module 2 and extracts the SQL from it and queries into the database. The EN module also receives the result set and converts it into an XML file and returns it back to the UI module which converts the results in user readable form and displays it.
So where does Integration testing comes into the picture?
Well, testing whether the information/data is flowing correctly or not will be your integration testing, which in this case would be validating the XML files. Are the XML files generated correctly? Do they have the correct data? Has the data been transferred correctly from one module to another? All these things will be tested as part of Integration testing.
Checking of data transfers between two components is called as an Interface Testing. It is a part of integration testing.
Interface testing includes testing of interfaces such as web services, APIs, connection strings that connect two components in the application. These interfaces don’t have a UI but takes an input and delivers output (do not confuse it with Unit testing).
Interface testing is done to check that the different components of the application/ system being developed are in sync with each other or not. In technical terms, interface testing helps determine that different functions like data transfer between the different elements in the system are happening according to the way they were designed to happen.
Let’s see how to test the Interface 2 in the above example considering that the interface takes an XML file as input from Component 4 and delivers a JSON file as output with a response message from the payment service provider. To test this interface we do not need to worry about the functionality of component 4. All we need is the specification of the XML file from Component 4 and the specification of JSON output. With the help of these specifications, we can create the sample input XML files and feed into the interface. The interface will pass the input to the payment service provider and returns an output JSON file. So in our example, validating the input file and the output file with the requirement is called Interface Testing.
Whenever developers change or modify the functionality/feature, there’s a huge possibility that these updates may cause unexpected behaviors. Regression testing is performed to make sure that a change or addition hasn’t broken any of the existing functionality. Its purpose is to find bugs that may have been accidentally introduced into the existing build and to ensure that previously removed bugs continue to stay dead. There are many functional testing tools available which support regression testing.
Let’s understand it by continuing our example of the leave management system. Let’s assume that developers have built a new feature(build 2) which shows the report of the employee’s leave history. Now, testers need to test this new feature by performing smoke testing with new test cases. Now, testers need to perform regression testing on build 2(Leave reports) to ensure that the code carried over from Build 1 (Leave application) behaves correctly. Here the main principle is reusing tests derived from Build 1. Also, the test case for build 2 would be a subset of build 1.
Regression testing can become a challenge for the testers as well. Here are some of the reasons:
- The Number of test cases in the regression suite increases with each new feature.
- Sometimes, the execution of the entire regression test suite becomes difficult due to time and budget constraints.
- Minimizing the test suite while achieving maximum test coverage is not a cake walk.
- Determination of frequency of Regression Tests after every modification or every build update or after a bunch of bug fixes is always a challenge.
When a new build is received with minor modifications, instead of running a thorough regression test suite we perform a sanity test. It determines that the modifications have actually fixed the issues and no further issues have been introduced by the fixes. Sanity testing is generally a subset of regression testing and a group of test cases executed that are related to the changes made to the product. Many testers get confused between sanity testing and smoke testing. Refer below image to understand the basic difference.
Let’s continue with the above example of the leave management system. Let’s assume that developers have released the build 2 with some other features. Now first we need to perform smoke testing and check whether the overall functionality is working fine. Here we are assuming that the build 2 has passed the smoke test. Now, we know that we’ve reported for “date selection” in build 1 and it has been solved in build 2. In sanity testing we’ll only test “date selection” functionality and whether it affects other functionalities.
System testing is testing conducted on a complete, integrated system to evaluate its compliance with the specified requirements.
After the completion of the integration testing, the product is passed for system testing. System testing is undertaken by independent testers who haven’t played a role in developing the program. This testing is performed in an environment that closely mirrors production. System Testing is very important because it verifies that the application meets the technical, functional, and business requirements that were set by the stakeholder.
In our example, we can perform system testing when all the modules are developed and passed integration successfully. For example, the complete product may include features like leave application, reports, employee details, performance tracker, etc.
User Acceptance Testing
User acceptance testing (UAT) is the last phase of the software testing process. In UAT actual software/app users test the software to make sure it can handle required tasks in real-world scenarios. Generally, it is performed at the time of product delivery to stakeholders as a final checkpoint among all functional testing types.
From starting to deployment, the software/app undergoes through various types of testing by testing team and developers. The end goal of all the efforts is to deliver a working software/app that fulfills users’ requirements and the client’s expectations. Both the teams become so familiar with the application that they might become a victim of tunnel vision. They are fully aware of workarounds and may skip certain scenarios which might be critical for end users.
The users are naive about how the application works. They are focused on ‘How the application should behave?’ They use the application with a fresh mind and whether it is intuitive to follow or not. UAT is based on user stories and establishes how well it meets their requirements. Users do not use ‘Test to Break’ approach while doing user acceptance testing. Rather, UAT is a measure of how good your application performs in normal scenarios.
At Simform, we believe that functional testing plays a crucial role in transforming client’s understanding of customer needs into applications that meet their requirements. Releasing applications with serious functional shortcomings can lead to disastrous consequences. When all the above functional testing types are performed at the right time in the development process, functional testing ensures the delivery of a quality product. Know more about our Software Testing Services.