50.003 - UI Testing¶
Learning Outcomes¶
- Describe the objectives of GUI testing
- Describe different types of GUI testing
- Develop automated GUI unit testing
- Develop automated end-to-end testing
The user interface is a software component that collects user input data, translates them into system expected input and present the results to the users.
There are many forms of user interfaces, e.g. visual, auditory, haptic, multimodal, and etc. In this module we only focus on visual user interface.
In modern computer system, we find many kinds of visual user interfaces.
- Command line
- Graphical user interface
- Chat bot
- ...
In this module, we put our attention to graphic user interface only.
Objective of Graphical User Interface Testing¶
There are two main objectives of conducting graphical user interface tests.
- To ensure functional correctness.
- To ensure visual correctness.
Functional GUI Tests are developed and conducted to ensure that the GUI component is behaving according to the functional requirements. Visual GUI Tests is to ensure that the GUI component is displayed and rendered according to the visual effect (non-functional) requirements.
Mode of UI Testing¶
Manual testing¶
Since UI is built for collecting input from human users, one way to test the UI components manually. Manual UI testing is labour intensive, as it requires enumerous amount of human resource and it is often mundane and repetitive.
Automated testing¶
Thanks to modern frameworks, there are approaches that allow tester to capture the human tester's behavior as a script and automate the testing.
Module Based UI Testing¶
Recall the earlier unit, testing is to find faults. It is often easier to find and isolate the fault if the software is developed in a modular way.
Example - Component Testing React.js App using Vitest¶
At the point when this note was written, it is recoomended to use
vitest
(which is an inplace replacement ofjest
) as the primary test library for React projects initiated usingvite
. All the syntax and APIs offerred invitest
are back-ward compatible withjest
.
Let's recall our echo app example introduced in the earlier units.
The Echo
Component consists of a NewMessageBar
component and a MessageList
component.
Let's recall the NewMessageBar
component, for the ease of testing, we move the following code
into a standalone file NewMessageBar.jsx
in the src/
folder.
We consider the following unit test case in Echo.test.jsx
.
render()
function takes a React Component and renders in the test environment. The screen
object allows us to make reference to the screen rendered in the test environment.
The getByText()
method takes a regex pattern which search for the text "submit" in upper or lower cases. The result is stored in the variable button
. Finally we assert that the button can be found in the rendered document. We argue that the above test case is leaning towards the visual test category.
We recall another component used in the Echo
app, MessageList
.
For the ease of reference, we give some test ids to the data rows and the table. We now can derive the following case.
In the above test case, we render a MessageList
component with an empty message list.
We expect the table's tbody
element should contains only one row, which is the the header row.
In the next test case,
we instantiate a MessageList
component with a singleton message list and expect that the
table should contains the message.
Note that both of the test cases are functional tests.
Finally let's consider testing the Echo
component. Recall that,
In the above code snippet, we abstract the backend API URL via the http_url
variable, for ease of mocking the API host.
We define two test cases of the Echo
component in the Echo.test.jsx
test file as follows.
As we want to isolate the test from the backend API, we need to mock the API calls. This is achieved by using the library msw
.
Due to some API deprecation, to import
msw
with versions of Jest and React we are currently using we need to introduce some extra configuration for Jest injest.polyfills
. For details setup, please refer to this file.
setupServer()
functions allows us to define a mock backend API server with the required endpoints.
The first test case 'testing initMessage() in Echo'
is to test the first rendering of the Echo()
component. We want to ensure that the table contains a row with the message returned by the mocked API /echo/all
.
Note that findByTestId()
is the async version of getByTestId()
, it waits for the previous promise to be fully resolved before assigning the result to the LHS variable.
The second test case 'testing submitNewMessage() in Echo'
is to test the user action of entering the message "bye" in the textbox and clicking the submit button. We want to assert that the table contains a row with the new message returned by the mocked API /echo/submit
.
Reference¶
https://testing-library.com/docs/
https://testing-library.com/docs/react-testing-library/example-intro
Cohort Exercise (Non graded)¶
Continue with your solution to Cohort Exercise 8 question 2, develop unit test cases for the React components found in the HR app.
UI-based end-to-end testing¶
An end-to-end (E2E) testing is to assess the built system's feature from the user's perspective. All the components in the system
supporting that particular feature are actively tested, i.e. no mocking.
An end-to-end test case is often derived directly from a use case.
To automate an end-to-end test, we can use test framework like Jest. For simple system feature like our Echo App. We could
define our test as follows (similar to the Echo.test.jsx
except that we don't require the mocking.)
In the above test case, we use Jest to simulate the user's action sequence
- randomly generate a text message.
- click on the submit button.
- check that the message is stored by the system database and returned in the message list.
For real world application, a use case is often much more sophiscated than the above example, and might requiring more than a single UI. It is more effective to perform E2E testing using web browser simulation frameworks such as Selenium, Puppeteer, Cypress and etc.
You are strongly encouraged to explore and incoporate one of the following in your project.
References¶
- Selenium
https://www.youtube.com/watch?v=BQ-9e13kJ58
- Cypress
https://www.youtube.com/watch?v=jX3v3N6oN5M
- Puppeteer
https://www.youtube.com/watch?v=GB4oJ1Ru1Nk