Всем привет! Меня зовут Алексей. В настоящее время я занимаюсь разработкой на платформе .NET, но моя история началась с работы QA Automation. И как вы уже поняли из названия статьи, речь пойдет именно об этой части моей жизни. И так как обмен знаниями - важный фактор развития. Мне бы хотелось предложить вам один из интересных способов тестирования веб-приложений. И здесь на сцену выходят Selenium и язык программирования C#, они могут работать в паре для создания эффективных автоматизированных тестов.

Помню, когда я только начинал свой путь в автоматизации тестирования, сталкивался с ограниченным количеством информации о взаимодействии Selenium и C#. В онлайн‑чатах и на форумах многие говорили: «Не получится так», «Попробуй другой язык программирования!». Звучит знакомо, верно?

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

Для чего все это !!!

Преимущества автоматизации тестирования

  1. Обеспечение высокой надежности:

    • Ошибки и дефекты в программном коде - неизбежная часть разработки.

    • Автоматизированное тестирование позволяет быстро и повторяемо выявлять проблемы на ранних стадиях разработки.

    • Это способствует высокой надежности и стабильности ПО.

  2. Сокращение времени цикла разработки:

    • Ручное тестирование требует значительных временных затрат.

    • Автоматизированные тесты могут быть быстро выполнены, даже в случае нескольких десятков и сотен тестовых сценариев.

    • Это сокращает общее время цикла разработки и ускоряет доставку продукта на рынок.

  3. Высокая скорость и точность:

    • Автоматизированные тесты выполняются значительно быстрее, чем те же тесты, проведенные вручную.

    • Отсутствие человеческого фактора и повторяемость действий гарантируют высокую точность тестирования.

  4. Повышение производительности команды:

    • Ручное тестирование может быть монотонным и трудоемким процессом.

    • Автоматизация освобождает тестировщиков от рутины и позволяет им фокусироваться на более творческих и аналитических задачах.

  5. Раннее выявление проблем:

    • Автоматизация позволяет проводить тестирование в режиме реального времени, на протяжении всего процесса разработки.

    • Это помогает выявлять и решать проблемы на ранних этапах, что снижает затраты на исправление дефектов впоследствии.

  6. Обеспечение совместимости и масштабируемости:

    • Автоматизированные тесты позволяют быстро проверять работоспособность ПО на различных конфигурациях и платформах.

    • Это особенно важно в современных условиях множественных устройств и браузеров.


Роль Selenium и C# в создании надежных автоматизированных тестов

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

Selenium - это как мощный детектив, который может заметить, что происходит на веб-странице. Он может найти кнопки, текстовые поля, выпадающие списки и многое другое. А C# - это язык, на котором можно "разговаривать" с Selenium и давать ему команды.

Вместе Selenium и C# - как динамичный дуэт. Они позволяют нам создавать тесты, которые будут проверять веб-сайт на ошибки. Например, мы можем сказать, чтобы они "нажали" кнопку "Войти" и проверили, что после этого появится правильное сообщение. Это как если бы вы проверяли, что все кнопки на вашем пульте дистанционного управления работают правильно.

Манипуляция с веб-элементами

При создании надежных автоматизированных тестов необходимо взаимодействовать с веб-элементами, такими как кнопки, текстовые поля и выпадающие списки. В этом процессе Selenium предоставляет инструменты для поиска и взаимодействия с элементами на странице, а C# дает возможность эффективно управлять этими элементами.

Клик на кнопку "Войти" на странице авторизации

IWebElement loginButton = driver.FindElement(By.Id("login-button"));
loginButton.Click();

Ввод текста в поле для поиска

IWebElement searchBox = driver.FindElement(By.Name("search"));
searchBox.SendKeys("Selenium testing");

Выбор опции "Черный" из выпадающего списка цветов

IWebElement colorDropdown = driver.FindElement(By.Id("color-selector"));
SelectElement colorSelect = new SelectElement(colorDropdown);
colorSelect.SelectByText("Черный");

Вход на сайт и проверка успешной авторизации

using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

[TestFixture]
public class LoginTests
{
    IWebDriver driver;

    [SetUp]
    public void SetUp()
    {
        driver = new ChromeDriver();
        driver.Navigate().GoToUrl("https://www.example.com/login");
    }

    [Test]
    public void TestSuccessfulLogin()
    {
        IWebElement usernameInput = driver.FindElement(By.Id("username"));
        IWebElement passwordInput = driver.FindElement(By.Id("password"));
        IWebElement loginButton = driver.FindElement(By.Id("login-button"));

        usernameInput.SendKeys("myUsername");
        passwordInput.SendKeys("myPassword");
        loginButton.Click();

        IWebElement welcomeMessage = driver.FindElement(By.CssSelector(".welcome-message"));
        Assert.AreEqual("Welcome, User!", welcomeMessage.Text);
    }

    [TearDown]
    public void TearDown()
    {
        driver.Quit();
    }
}

Создание структурированных тестов

Структурирование тестов позволяет улучшить их управляемость и читаемость. C# предоставляет средства для создания структурированных тестовых классов и пространств имен.

Организация тестовых методов с использованием классов

public class TestSuite
{
    [Test]
    public void TestLogin()
    {
        // Ваш код для тестирования авторизации
    }

    [Test]
    public void TestSearch()
    {
        // Ваш код для тестирования поиска
    }
}

Использование пространств имен для разделения функциональности тестов

namespace TestSuite.Authentication
{
    // Тесты для авторизации
}

namespace TestSuite.Search
{
    // Тесты для поиска
}

Группировка тестов в наборы с использованием атрибутов

[TestFixture("Chrome")]
[TestFixture("Firefox")]
public class CrossBrowserTests
{
    private string browser;

    public CrossBrowserTests(string browser)
    {
        this.browser = browser;
    }

    [Test]
    public void TestHomePage()
    {
        // Ваш код для тестирования главной страницы
    }
}

Кроме того, Selenium и C# помогают нам ожидать, когда важные вещи произойдут на веб-странице. Например, мы можем сказать им подождать, пока загрузится нужный элемент, прежде чем продолжать. Это как если бы вы дали себе немного времени, чтобы дождаться, когда ваш друг придет на встречу.

Управление ожиданиями

Ожидания играют ключевую роль в создании стабильных автоматизированных тестов. Selenium и C# совместно предоставляют инструменты для эффективного управления ожиданиями.

Ожидание загрузки элемента с использованием явного ожидания

Явные ожидания позволяют ждать определенное состояние элемента перед его взаимодействием. В данном примере мы будем ожидать, когда кнопка «Отправить» станет кликабельной.

IWebElement sendButton = driver.FindElement(By.Id("send-button"));

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.ElementToBeClickable(sendButton));

sendButton.Click();

Ожидание наличия элемента с использованием неявного ожидания

Неявные ожидания автоматически применяются ко всем действиям WebDriver, ждущим элемент на странице в течение определенного времени. В этом примере мы будем ожидать, что элемент с id "result" появится на странице.

driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);

IWebElement resultElement = driver.FindElement(By.Id("result"));
string resultText = resultElement.Text;

Ожидание исчезновения элемента после удаления

Часто требуется ожидать, когда элемент исчезнет после какого-либо действия. В этом примере мы будем ожидать, что элемент с классом "loading-spinner" исчезнет после успешной загрузки страницы.

IWebElement loadingSpinner = driver.FindElement(By.ClassName("loading-spinner"));
// Предположим, что загрузка завершится и элемент исчезнет через несколько секунд

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.ClassName("loading-spinner")));

// Продолжение выполнения теста после завершения загрузки

Ожидание изменения значения элемента после действия

Иногда требуется ожидать, когда элемент изменит свое значение после какого-либо действия. В этом примере мы будем ожидать, когда текст на кнопке изменится на "Готово" после ее клика.

IWebElement button = driver.FindElement(By.Id("action-button"));
button.Click();

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(ExpectedConditions.TextToBePresentInElement(button, "Готово"));

Ожидание наличия элемента перед выполнением действия

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

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement element = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("element-id")));

element.Click();

Ожидание наличия элемента во фрейме

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

driver.SwitchTo().Frame("frame-name");

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement elementInFrame = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("element-id")));

elementInFrame.Click();

// Вернуться на основную страницу после завершения действий во фрейме
driver.SwitchTo().DefaultContent();

Ожидание асинхронной загрузки элемента

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

IWebElement asyncLoadedElement = driver.FindElement(By.Id("async-loaded-element"));

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(driver => asyncLoadedElement.Displayed && asyncLoadedElement.Enabled);

asyncLoadedElement.Click();

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

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

Параметризация тестов

Параметризация позволяет создавать универсальные тесты, которые могут быть применены к различным сценариям.

Передача параметров в тестовый метод

[TestCase("user1", "password1")]
[TestCase("user2", "password2")]
public void TestLogin(string username, string password)
{
    // Ваш код для тестирования авторизации с разными учетными данными
}

Использование конфигурационных файлов для хранения параметров

string username = ConfigurationManager.AppSettings["username"];
string password = ConfigurationManager.AppSettings["password"];
// Ваш код для тестирования авторизации с параметрами из конфигурационного файла

Интеграция с фреймворками

Интеграция с фреймворками упрощает создание и запуск тестов.

Интеграция с фреймворком NUnit

[TestFixture]
public class NUnitTests
{
    [Test]
    public void TestMethod()
    {
        // Ваш код для тестирования
    }
}

Интеграция с фреймворком MSTest

[TestClass]
public class MSTestTests
{
    [TestMethod]
    public void TestMethod()
    {
        // Ваш код для тестирования
    }
}

Использование атрибутов xUnit

public class XUnitTests
{
    [Fact]
    public void TestMethod()
    {
        // Ваш код для тестирования
    }
}

И наконец, благодаря Selenium и C#, мы можем управлять тем, что происходит, когда что-то идет не так. Например, если кнопка не появляется на странице, мы можем сказать, что это нормально и не нужно пугаться. Это как если бы вы знали, что даже если погода не совсем хорошая, вы все равно можете найти способ весело провести время.

Обработка исключений

Обработка исключений позволяет эффективно управлять возможными ошибками в процессе выполнения тестов.

Использование конструкции try-catch для обработки исключения ElementNotVisibleException

try
{
    IWebElement element = driver.FindElement(By.Id("hidden-element"));
    element.Click();
}
catch (ElementNotVisibleException ex)
{
    // Ваш код для обработки исключения
}

Обработка WebDriverException при потере соединения с браузером

try
{
    driver.FindElement(By.Id("element-id")).Click();
}
catch (WebDriverException ex)
{
    // Ваш код для обработки исключения
}

И вот, мы можем создавать надежные и точные тесты для веб-сайтов. Они помогают нам убедиться, что программа работает правильно и пользователи не столкнутся с неприятностями. Это как будто у нас есть свой личный команда-исследователей, которая следит за качеством наших веб-приключений.

Использование Assert для проверки наличия элемента перед взаимодействием

IWebElement element = driver.FindElement(By.Id("element-id"));
Assert.NotNull(element, "Элемент не найден");
element.Click();

В заключение хочется сказать, что мы только немного заглянули в удивительный мир возможностей, который предоставляют нам Selenium и язык программирования C#. Мы рассмотрели лишь небольшую часть того, как совмещение способности Selenium взаимодействовать с веб-элементами и управлять ими с гибкостью языка программирования C# дает вам мощные инструменты для создания надежных автоматизированных тестов .

Пробуйте, экспериментируйте и наслаждайтесь результатами, которые помогут вам обеспечить высокое качество вашего программного продукта.

Комментарии (10)


  1. Kormakk
    28.08.2023 17:23
    +2

    А инновационное здесь что?


    1. Aleksey_Zabrodin Автор
      28.08.2023 17:23

      Долгое время Java и Python являются наиболее распространенными языками для автоматизации с Selenium, в статье я пытаюсь показать что связка C# и Selenium , тоже имеет право на существование и является очень мощным инструментом.
      Инновационные подходы описанные в статье это: Эффективное взаимодействие с веб-элементами, Гибкое управление ожиданиями, Интеграция с фреймворками, Обработка исключений, C# демонстрирует высокую производительность и стабильность.


      1. s207883
        28.08.2023 17:23
        +1

        Этого же самого нельзя добиться на Жабе и Питоне? Вроде можно, жаба так ничем, в этом плане, не уступает. И так, что тут инновационное?

        Лично наблюдал несколько лет назад внедрение селениума в проект на C# и даже тогда это не было каким-то хай-теком.


  1. Bagir123
    28.08.2023 17:23

    А в чем преимущества?

    Я сам программирую на этой связке. Что радует, то это скорость обработки. Допустим спарсить миллион товаров на c# с отслеживанием дубликатов (а интернет сайты имеют обыкновение перемешивать товар в каталоге) на c# удобнее.

    Но с другой стороны как язык компилируемый c#, как я понимаю, уступит в отладке интерпретируемому питону.


    1. Aleksey_Zabrodin Автор
      28.08.2023 17:23

      Ответ ???? )))


  1. Aleksey_Zabrodin Автор
    28.08.2023 17:23

    Каждый инструмент предназначен для своих целей, тяжело закручивать болт отвёрткой, у каждого языка свои преимущества и недостатки при решении тех или иных задач, одни более подходят - другие менее , область применения С# все больше расширяется и его мощность при этом не страдает.


  1. RussianTM
    28.08.2023 17:23

    Работа с Selenium должна напоминать Playwright - все эти костыли по внезапному исчезновению элемента (Привет Angular + DevExtreme + StaleElementReferenceException) должны быть убраны из глаз тестировщика.

    Тестировщик должен оперировать только неким локатором (неким XPath) и действиями над ним. Попробую в ближайшее время написать как мы переезжали на такой формат.


    1. Aleksey_Zabrodin Автор
      28.08.2023 17:23

      Полностью согласен, у нас каждому элементу был задан свой ID и работа с элементами заиграла новыми красками)))

      Но этому нужно посвещать отдельную статью.


    1. Bagir123
      28.08.2023 17:23

      Ну это смотря что тестировать. Например, как Вам тестирование капчи? :)


      1. Aleksey_Zabrodin Автор
        28.08.2023 17:23

        Не самое простое занятие, но в C# существуют библиотеки, которые можно использовать для работы с капчей. Вот некоторые из них:

        1. DeathByCaptcha: Это популярный сервис, предоставляющий API для разгадывания капчи. Они также предоставляют библиотеку для C#, которая упрощает взаимодействие с их сервисом.

        2. TwoCaptcha: Подобно DeathByCaptcha, это ещё один популярный сервис и API для разгадывания капчи. Они также предоставляют библиотеку для C#.

        3. Anticaptcha: Это ещё один сервис и API для разгадывания капчи. Они также имеют библиотеку для C#.

        4. Speech recognition библиотеки: Если капча представлена в виде аудиофайла с голосовой задачей, можно использовать библиотеки для распознавания речи, такие как Microsoft Speech SDK.

        5. Автоматизация браузера: Если капча встроена на веб-странице, вы можете использовать Selenium WebDriver для взаимодействия с капчей, заполняя её вручную или анализируя результаты.