A portrait of Alex Turner
08 Aug, 2023 6 min read

Testing a Project

An insight into some of the methods we use at Steadfast Collective when testing out a software development project
Testing a Project

Tools for testing our stack

Testing is an essential part of software development that ensures the quality, reliability, and functionality of a software product. It gives you the confidence that the code you’ve just written will run smoothly with no defects… Even if the code is getting released on a Friday afternoon.

Testing involves using a framework, program or application to find errors, bugs, and other defects that may affect its performance or usability. Through testing, developers can identify and resolve issues before releasing the software to end-users.

There are many different ways to test applications. This article will give an overview of each of the different types of testing we do at Steadfast Collective.

Unit Testing

Unit testing is focused more towards testing individual components of an application. The purpose of unit testing is to ensure that each component of the application works as intended and to catch any bugs as early as possible.

Unit testing will typically involve writing automated tests for each component that performs a task in an application.

At Steadfast, we are fans of TDD (Test-Driven Development). TDD is a practice in which the unit tests are written before any of the code, and then the test is used to drive the code which is added to the codebase.

It’s called ‘Unit’ testing because each test is supposed to be concerned with a ‘unit’ of code. This means the simplest part of an application/codebase that can be isolated. For example, perhaps you have a function that returns a greeting, when provided with a name.

<?

function greetUser($name)
{
	return "Hello, $name!";
}

This function takes a single parameter $name and returns a string saying “Hello, [name you passed]" as an argument. This is a good example of something that could be unit tested because it has a predictable outcome that can be asserted as true or false when tested.

The test for this ‘unit’ of code could look like the following:

<?php 

function test_greet_user_returns_the_correct_greeting()
{
	$greeting = greetUser('John');
	
  	assert($greeting === 'Hello, John!');
}

Here we are passing the result of greetUser into a variable called  $greeting. We then assert that $greeting returns “Hello, John!” as we would expect when passing the name “John” into the greetUser function. It might seem overkill to create tests for such small pieces of code - but it provides a lot of benefit.
For one it allows us to be sure that we haven’t overlooked anything small, and are getting precisely what we want out of the code we’ve written.

Secondly, it’s useful for ensuring any code changes you make elsewhere in the application do not cause regressions. That is unintentional issues/bugs that break preexisting functionality.

Handily PHP Unit ships standard with Laravel, which makes writing unit tests from the get go very easy.

Another tool that is built on top of PHP Unit that we love is Pest.
Pest is an open-source tool created to enhance PHP Units existing features, and provide nicer user output. The console output is greatly improved, providing much more useful feedback to help you understand what might be breaking in your tests. It also alters the syntax to be more readable.

Instead of writing function test_greet_user_returns_the_correct_greeting, we would instead write test(‘greetUser() returns the correct greeting’). This much more natural syntax makes it a lot easier to read dozens of tests at a glance, thus maintaining them.

E2E Testing

Whereas unit testing is focused around testing individual components of an application, E2E testing (end-to-end testing) is focused towards testing an entire application from end-to-end. E2E testing is focused on simulating real world usage and interactions, like the user interface and interactions from the user.

Although E2E testing can be a manual process there are many tools to help automate it by simulating user interactions across multiple platforms and environments.

One such tool is Playwright. Playwright allows you to create tests that evaluate the state of your website as it would be viewed by a user, and it interacts with your site in much the same way as a user.

Take for instance this example:

test('has title', async ({ page }) => {
  await page.goto('https://my-website.com/');

  // Expect a title "to contain" a substring.
  await expect(page).toHaveTitle(/My Website/);
});

First we use the page.goto call to tell Playwright to navigate to the url we want. In this case our homepage.

Then with a straightforward 'expect' call we check if the page has the 'My Website' title we want it to.

This allows us to test exactly how we want our web pages to appear, and extends to many other aspects including links, buttons, urls - anything a web page can contain, essentially.

Through a combination of something like PHP Unit and Playwright you can test both the back end and front end of your application.

Acceptance Testing

Unlike unit testing, which focuses on testing individual components of the application in isolation, and end-to-end (E2E) testing, which simulates real-world usage and interactions, acceptance testing takes a broader perspective. It evaluates the software as a whole, verifying that all the integrated components work together as intended and deliver the desired functionality.

Types of Acceptance Testing:

  1. User Acceptance Testing (UAT): User Acceptance Testing involves end-users or representatives from the target audience to validate the application's usability and functionality from their perspective. During UAT, real users interact with the software, perform typical tasks, and provide feedback on its performance. The feedback received during UAT is crucial for making any final adjustments before the official release.

  2. Business Acceptance Testing (BAT): Business Acceptance Testing is conducted by the business stakeholders or subject matter experts (SMEs) to ensure that the application aligns with the predefined business requirements and processes. This type of testing focuses on verifying that the software meets the business objectives and can support the necessary workflows efficiently.

  3. Regulatory Acceptance Testing: In some industries, applications must comply with specific regulations and standards. Regulatory acceptance testing ensures that the software meets all the required regulatory guidelines and operates in accordance with industry-specific requirements.

Tools for Acceptance Testing:

  1. Cucumber: Cucumber is a popular acceptance testing framework that supports Behaviour-Driven Development (BDD). It allows stakeholders, developers, and testers to collaborate effectively by expressing test scenarios in a human-readable format. Tests written in Gherkin (Cucumber's language) can be easily understood by non-technical team members, fostering better communication and alignment.

  2. Selenium: Selenium is widely used for functional and acceptance testing of web applications. It allows testers to automate interactions with web browsers, simulating user behaviour and validating application functionality across different browsers and platforms.

Conclusion:

Acceptance testing is the final step in the testing process before software release. It plays a vital role in ensuring that the application meets the expectations of its users and aligns with the business requirements.

By conducting thorough acceptance testing and incorporating feedback from stakeholders, development teams can be confident in the quality, reliability, and functionality of the software they are delivering to their users. Effective acceptance testing contributes to a successful software launch and a positive user experience.

Software