Автоматизированное тестирование веб-приложения с нуля (MS Unit Testing Framework + Selenium WebDriver C#)

в 14:26, , рубрики: Microsoft Unit Testing Framework, Selenium WebDriver C#, автоматизированное тестирование, тестирование, метки: , , ,
Введение


Всем Buenos Dias! В своей статье я хотел бы максимально лаконично и просто рассказать о том, как построить процесс автоматизированного тестирования web-приложения с нуля. Первым делом нужно правильно расставить приоритеты и выбрать приемлемое соотношение цена/качество. Сразу определимся — это будет не решение «на коленках» из зоопарка скриптов, которыми часто пользуются при ручном тестировании. В тоже время мы не будем тратить много усилий на проектирование нашего «фреймворка» для автоматизации. Наша цель — предоставить результаты своей бурной деятельности перед руководством в максимально короткие сроки, при этом система должна быть:

  • максимально простой, чтобы тесты могли писать даже специалисты по ручному тестированию
  • гибкой и расширяемой, поскольку мы не можем адекватно оценить весь объем работ на данном этапе
  • кроссплатформенной (Selenium WebDriver C# поддерживает Firefox, Chrome и IE)

В своем примере я буду успользовать .NET (Microsoft Unit Testing Framework) и Selenium WebDriver C#.

Поехали

Итак, первым делом необходимо отобрать некоторое количество тестовых сценариев высокого приоритета, но довольно простых.
Далее создадим в студии новый solution. Вполне логично будет создать в нем 3 проекта: тесты, описание страниц и утилиты. Это и будут наши три базовые сущности.

image

Схема будет довольно простая: тест работает со страницами, запрашивая на них какие-либо данные или выполняя там какие-либо действия. В утилитах мы разместим классы, которые будут отвечать за работу c браузером и web-элементами на страницах посредством Selenium WebDriver. Вполне логично написать обертки (wrapper), поскольку Selenium WebDriver API имеет множество недостатков и может показаться довольно неудобным. Именно в этих обертках мы инкапсулируем (спрячем) весь специфический и некрасивый код. Для примера, создадим классы Browser и WebElement, которые предоставят разработчикам автотестов только тот футкционал, который им нужен. В дальнейшем я хотел бы описать этот процесс в отдельной статье, поэтому не буду останавливаться.

Тесты

Определимся с тем, что будут представлять собой наши тесты. Не будем изобретать велосипед — в идеале тест состоит из 4 частей:

  • входные (тестовые) данные
  • предусловие, т.е. некоторое состояние системы, при котором мы сможем выполнить необходимую проверку
  • взаимодействие с web-приложением
  • проверка — сравнение ожидаемого результата с полученным. В MS Unit Testing Framework для этого существует отдельный класс Assert

При этом важно обеспечить атомарность тестов — тест должен проверять одну логическую операцию и в идеале иметь одну единственную проверку. Плюсы данного подхода следующие:

  • сокращение времени анализа результатов тестов
  • не нужно тратить время на реализацию масштабного логирования (не стоит забывать, что MS Unit Testing Framework умеет собирать всевозможную диагностическую информацию в процессе выполнения теста, например: стэк вызовов, лог событий, IntelliTrace, запись фото и видео, анализ кодового покрытия)

Описание web-страниц тестируемого продукта

Что же будут представлять из себя описания страниц?
Во-первых, это описания элементов, с которыми мы будем работать, т.е. способ распознавания их по id, классу, имени, xpath и др. Не надо описывать сразу все имеющиеся на странице элементы, это нерациональная трата времени. При этом все эти описания должны быть приватными и не выходить за рамки класса страницы.
Во вторых, страница будет содержать свойства (getters) и методы, с помощью которых тесты смогут получить информацию со страницы, например значение какого-нибудь текстового поля.
И в третьих, страница будет содержать методы для совершения действий на самой странице, например клик по кнопке. Важно отметить, что описание страницы не должно содержать никакой логики и никаких проверок! Проверки должны быть в тестах. И в то же время, здесь не должно быть никаких вызовов Selenium WebDriver API.

Утилиты

В данном проекте, как минимум, будут находится обертки над Selenium WebDriver API. В последствии это место станет скоплением всевозможных helper'ов, утилит, расширений и т.д. до их вынесения в отдельные сущности и проекты.

Заключение и пример

Таким образом, нужно четко разграничить логику наших автотестов, для этого мы и создали три отдельных проекта. Я не исключаю, что в процессе развития проекта появятся и другие логические уровни со своими сущностями, но минимум будет такой.

Далее я покажу один простой пример и на этом закончу статью. Если она окажется интересной, я обязательно напишу продолжение, где опишу детали реализации тестов, страниц и оберток над WebDriver API.

[TestClass]
public class LogOnTests : TestsBase
{
    [TestMethod]
    public void LogOnWithEmptyLogin()
    {
        #region TestData

        const string login = null;
        const string password = "password";
        const string error = "Empty login!";

        #endregion

        Browser.Open(...);
        LogOnPage.LogOn(login, password);

        Assert.AreEqual(error, LogOnPage.Error,
            "Error expected.");
    }
}

public static class LogOnPage
{
    private static readonly WebElement LoginEdit = new WebElement().ById("Login");
    private static readonly WebElement PasswordEdit = new WebElement().ById("Password");
    private static readonly WebElement LogOnButton = new WebElement().ById("LogOn");
    private static readonly WebElement LogOnValidationError = new WebElement().ById("LogOnValidation");

    public static void LogOn(string login, string password)
    {
        LoginEdit.Text = login;
        PasswordEdit.Text = password;
        LogOnButton.Click();
    }

    public static string Error
    {
        get { return LogOnValidationError.Text; }
    }
}

P.S. Вспомнилась старинная русская поговорка: кто рано встает, тот отлаживает тесты.

Автор: natexriver

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js