
Acceptance Test Automation Selenium + .NET Web Api + AngularJs
- Tutorial

I will tell how we in the company work with acceptance tests. In the article, you will find a link to the repository with code and a video with an example of work.
Not all tests are equally useful.
Some time ago, a debate was relevant - "Should the developer test his code?". Yes, the developer must test what he creates. I think that now few argue with this statement.
The next question was “How should a developer test his code?” The answer to this question was found - TDD. In an ideal world, a developer develops most of the functionality through tests. As a result, we get a good code design that is convenient to maintain and modify, plus a set of test cases that allow the developer to make changes to the existing code with peace of mind.
It happens in an ideal world. In fact, it is not always possible to carry out all development through testing. Even if all development is performed using TDD, we still cannot say that the system being developed will work properly at the customer’s start.
Unit tests do not affect the environment - if you need to test a service that contacts the database for data, the developer writes a stub for the database. If you need to check a service that accesses an external service, the developer writes a stub that emulates the operation of this service.
The next step is the configuration and integration tests, which introduce the physical elements of the system into the virtual test environment - database servers, hardware firewalls, and third-party software. The implementation of such tests allows us to say that the system "correctly" interacts with the environment. But even the “right” interaction with the environment does not guarantee us that in the end the system will work as expected - according to the scripts that are described in the specification.
As my practice shows, the most useful testing is acceptance testing. By acceptance testing, I mean the following:
- A test site is created as close as possible to the production configuration
- The test site includes hardware and software components - firewalls, servers, third-party software, etc.
- At this site, tests are performed according to the scenarios that are prescribed in the acceptance methodology for testing the system (hello GOST 34)
- On the site, the main cases are checked for which the user works with the system
If you manage to raise such a platform (which is often difficult to do), and check all test cases according to the specification scenarios, then with high probability we can say that the system works as expected and, as a result, does not contain errors.
Errors will certainly be, but performing acceptance testing makes it more likely (as compared to unit and integration testing) to detect errors.
Automate acceptance testing
Acceptance test automation comes down to the following steps:
- Write acceptance test scripts
- Develop tests based on Selenium
- Automate the process of running execution tests after changing the code in the repository
Acceptance Test Scenarios
We record acceptance test scripts as use case scripts in specifications. The specifications are developed by the analyst based on functional, user, non-functional and other requirements.
To maintain specifications, we use the Atlassian Confluence in conjunction with the Balsamiq Mockups .
Test development based on Selenium
To develop tests, we created our own solution that allows you to:
- Design tests based on the PageObject pattern
- Run tests on different browsers
- In case of a test error, get a screenshot, a copy of the html pages and the name of the test case
The development of new tests comes down to the description of the tested page - PageObject and the development of the steps of the test case.
The project with acceptance tests looks like this:

Main components:
- Common \ BasePage.cs - base classes for describing PageObject pages. Contains helper methods for finding elements on a page using various selectors.
- Common \ BaseTest.cs is the base class for all acceptance tests. It contains the logic of starting / stopping browsers to run tests, the logic of waiting for the completion of all active $ http client application requests.
- PageObjects - the directory contains pages for the client application. The Page Object page encapsulates knowledge of page elements and the actions that can be performed on a page.
- TestCases directory - contains cases for running tests
The test consists of steps - Step (). A step can perform an action and verify that some statement is complete. The following is an example test:
- Open authorization page
- Login as administrator
- Open report
- Block Report
- Edit two cells "110" and "220"
- Save changes
- Unlock report
- Make sure that in the “GOU” cell the amount is calculated according to the entered values - “110” + “220”
Test code:

The video shows the test.
If an error occurred during the test - authorization failed, the report did not open, etc., then a screenshot of the page, browser name, test name and html error page will be saved in the directory specified in app.config.
Determining the completion of all $ http requests of an AngularJS application
The client SPA application performs requests to the server using the $ http service. For example, when you open the "Daily Statement" report, an asynchronous call to the server is performed. In response, the client receives report data from the server.
In test cases, you must be able to wait for all requests to complete. For example, a client application after going to the report takes time to download data from the server. After the data is downloaded and displayed on the page, you should test this page.
To track the completion of all $ http requests, I use the following approach:
- A variable is created in the client application that contains the number of active $ http requests
- An injection is made into the $ http service, which increases the variable by 1 when sending the request and decreases the variable by 1 when the request is successful or unsuccessful
- Selenium checks the value of this variable to ensure that the client has completed processing the request.
Running Acceptance Tests with TeamCity
As a continuous integration server we use TeamCity.
After the developer sent the code to the repository, TeamCity deploys the test site and runs acceptance tests on it. Thus, after each code change, the project is installed and tested from scratch. This solution saves a lot of time plus allows us not to think about regression testing.
The main steps:
- Clear site directory from old build
- Configure application app.config - configuration of connection strings from the test database is performed
- Build a project - launch MSBuild
- Stop IIS
- Delete old test database
- Create a new test database
- Copy application files to the site directory
- Launch IIS
- Run acceptance tests
Who writes acceptance tests
Acceptance tests can be written both by the developer - upon completion of the script implementation, and by the testing engineer specially dedicated to the task data.
Source
The source code for the test application is available on github .
Conclusion
Automate acceptance testing is possible and necessary. The advantages of this approach:
- There are guarantees that the repository contains working code that will be compiled, installed on the site and will work properly according to the specification scripts
- Manual testing time is reduced - the test is written once and executed every time the code is changed
- Regression testing time is reduced
- The time for searching and documenting errors is reduced - if the test fails, then the playback steps are recorded in the logs and a screenshot is attached
- The cost of fixing errors is reduced - an error found in the office will cost less than an error found at the customer
At the end of the article I will say that for large and long projects that last half a year or more - the presence of automated acceptance tests is a prerequisite for ensuring the required quality of the product.