As a QA professional, creating a new user for product testing may seem like a simple task – just complete the registration form and you're ready to go. However, what if you need to test a user with a year-long message history, or evaluate how a video service feature works for a particular A/B testing group? These situations can quickly become tedious and time-consuming when creating users manually.
In this article, we will share our journey of developing a tool that fully automates that process. Let's dive in!
Introducing our User Management Tool
At Social Discovery Group, we provide online services that connect people around the world. Our products enable users to communicate through chat and video, and share media content. As our products evolved, we started to encounter increasingly complex test scenarios. For example, we needed to examine a user's profile with an expired subscription or analyze the functionality of a contact list with over 30 entries.
To generate a "history-rich" user, we had to execute multiple API queries, send messages to RabbitMQ, and run SQL scripts. As these steps were already incorporated into our automated tests, the manual QA team frequently asked us to perform an automated test to create the needed user. Over time, the creation of a single user started to take longer than the testing itself. Therefore, we decided to find a way to empower any employee to handle the user creation process independently.
Our test automation is written in C#. We actively utilize API calls to our application resources in automated tests. For instance, we use the following method for client registration:
var client = new Client();
RegisterClient(client, param1, param2, param3);
After analyzing our framework, we concluded that the easiest solution for creating the necessary users for testing would be to develop an ASP.NET Web Forms application using our methods. We envisioned a website that QA testers could use to easily create the required users.
Here's what we did:
First, we added a page for user creation. Testers could select additional parameters and configure the user according to their preferences – either as a new user or with a long history of chats.
Here's what the process looked like:
Here is the code for the page, including the output element.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs"
Inherits="Habrl.Pages.Registration.RegistrationForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="registration" runat="server">
<div>
<div>
<label>Client type:</label>
<asp:DropDownList ID="clientType" runat="server" AutoPostBack="true"
CssClass="select" OnSelectedIndexChanged="clientType_OnSelectedIndexChanged">
<asp:ListItem value="regularClient" Selected="True">Regular client</asp:ListItem>
<asp:ListItem value="clientWithChatHistory">Client with chat history</asp:ListItem>
<asp:ListItem value="inactiveClient">Inactive Client</asp:ListItem>
</asp:DropDownList>
</div>
<div id="usersCountDiv" runat="server">
<label>How much clients we should register:</label>
<asp:TextBox ID="clientsCount" runat="server" CssClass="input"
Text="1"></asp:TextBox>
<div class="errorMsg">
<asp:RequiredFieldValidator Display="Dynamic" runat="server"
ControlToValidate="usersCount" ErrorMessage="Define clients
count!"></asp:RequiredFieldValidator>
<asp:RangeValidator Display="Dynamic" runat="server"
ControlToValidate="clientsCount" Type="Integer" MinimumValue="1" MaximumValue="30"
ErrorMessage="We can create from 1 till 30 clients at once!"></asp:RangeValidator>
</div>
</div>
<div>
<asp:Button CssClass="MyButton separateButton" ID="SubmitButton" runat="server"
text="Register" OnClick="OnRegisterButtonClick"></asp:Button>
</div>
</div>
</form>
<div runat="server" id="result"></div>
</body>
</html>
Here’s the logic implementation:
public partial class RegistrationForm : System.Web.UI.Page
{
int _clientsCount;
string _clientType;
protected void Page_Load(object sender, EventArgs e)
{
_clientsCount = int.Parse(clientsCount.Text);
_clientType = clientType.SelectedValue;
}
protected void OnRegisterButtonClick(object sender, EventArgs e)
{
var clients = new ConcurrentBag<Client>();
Parallel.For(0, _clientsCount, _ =>
{
var client = new Client();
RegisterClient(client, _clientType);
clients.Add(client);
});
result.InnerHtml = GenerateTableViewForClientsEnumerable(clients);
}
}
Upon registering, we receive the following table:
The RegisterClient method used in UMT is identical to the one used in our autotests. This means that whenever we introduce new functionality to our products, our autotests are automatically updated, and those changes are reflected in UMT as well. UMT essentially serves as a front-end implementation over our contracts, which provide the underlying autotest code.
Thanks to UMT, the entire team can now easily create the required user profile in any of our numerous testing environments with just a couple of clicks. The manual QA team can generate even the most intricate user profiles independently, without requiring any involvement from the automation team. To our surprise, the development team has also started to leverage UMT for their purposes.
Development and Improvement
After we released UMT, we began to receive requests for new features. We added pages for user management (including online status emulation and messaging) and payment management. Later, the mobile team approached us with a concern: creating a UMT user on mobile devices required a lot of time and effort to input email and password details. In response, we added a small but useful feature to UMT – the generation of QR codes with login links and deep links for mobile applications.
As we continued to develop UMT, we underwent two major redesigns and added a tree-like menu to the site. As a result, the original user registration page has undergone significant transformation and now looks entirely different.
Over the course of UMT's five-and-a-half-year existence, we expanded the tool far beyond its original purpose of facilitating product testing. We added sections to automate DevOps activities, such as restarting services and servers, configuring, cleaning, and linking test environments, and providing statistical information, as well as a knowledge base and more. In the next section, I will take a closer look at some of these features.
Authorization
After a while, we decided to restrict access to UMT for certain employees (for example, those on probation). To do this, we added a database and a table with roles and users, implemented domain authentication, and assigned permissions. With this system in place, we can identify the user session and give the user access to specific functionality based on their rights. We also added Google authorization to UMT, given our company's use of Google services.
Services and test environment
As UMT became a popular tool among the team, our QA team wanted to manage services and test beds through UMT instead of relying on various scripts and tools like Ansible. We added the ability to restart Docker and Windows services, IIS, and web nodes, and edit the configs of those services. We also included a feature for configuring these services and comparing them across test beds.
TestRail and Jenkins
Test automation is a crucial part of our work, and we often have more than ten test runs in progress at any given time. However, it can be challenging to locate a particular run among many others in Jenkins or to check its position in the queue. To address this issue, we developed a page in UMT that displays data on all current runs and those in the queue. This page polls all of our Jenkins instances to collect information about running jobs, which is then presented in tables for easy reference.
Additionally, UMT offers a separate page for creating TestPlans with TestRuns enabled in TestRail. With just a few clicks, users can choose from several basic TestPlans with testing scenarios.
UMT has also proven useful for parsing failed autotests or investigating anomalous user behavior. Previously, these tasks required manually opening Fiddler for API queries or connecting to the database to execute SQL queries. With UMT, however, dedicated pages provide comprehensive technical information on users created in the test bed, making problem-solving faster and more efficient.
Today, UMT is a full-fledged project that continues to evolve as the test automation department receives new tasks for adding functionality or fixing bugs. Prioritized tasks are included in the sprint. UMT remains an essential tool for our staff, saving them time and effort by collecting many routine activities in one place. There is no longer a need to take notes, save API queries to Fiddler or Postman, or open SQL Studio to perform database routines. So if your company faces similar challenges, you now know what to do.
Written by Pavel Yasonau, Team Lead QA Automation at Social Discovery Group