Автоматизация приемочного тестирования Selenium + .NET Web Api + AngularJs

  • Tutorial

Я расскажу как мы в компании работаем с приемочными тестами. В статье вас ждет ссылка на репозиторий с кодом и видео с примером работы.

Не все тесты одинаково полезны


Некоторое время назад был актуален спор — «Должен ли разработчик тестировать свой код?». Да, разработчик должен тестировать то что он создает. Думаю, что сейчас с этим утверждением мало кто поспорит.

Следующий вопрос был — «Каким образом разработчик должен тестировать свой код?». Ответ на это вопрос был найден — TDD. В идеальном мире разработчик большую часть функционала разрабатывает через тесты. В качестве результата получаем хороший дизайн кода, который удобно поддерживать и модифицировать, плюс набор тест-кейсов, которые позволяют разработчику со спокойной душой вносить изменения в существующий код.

Это происходит в идеальном мире. По факту не всегда получается всю разработку выполнять через тестирование. Даже если вся разработка выполняется при помощи TDD, то мы все равно не можем сказать, что разрабатываемая система при запуске у заказчика будет исправно работать.

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

Следующим этапом появляются конфигурационные и интеграционные тесты, которые вносят в виртуальную тестовую среду физические элементы системы — сервера БД, аппаратные межсетевые экраны, стороннее программное обеспечение. Реализация таких тестов позволяет нам сказать, что система «правильно» взаимодействует с окружением. Но даже «правильное» взаимодействие с окружением не гарантирует нам, что в итоге система будет работать ожидаемо — по сценариям, которые описаны в спецификации.

Как показывает моя практика — самым полезным тестированием является приемочное тестирование. Под приемочным тестированием я понимаю следующее:

  • Создана тестовая площадка максимально приближенная к конфигурации продакшена
  • Тестовая площадка включает в себя аппаратную и программную составляющую — межсетевые экраны, сервера, стороннее ПО и т.д.
  • На данной площадке выполняются тесты по сценариям, которые прописаны в приемочной методике испытания системы(здравствуй ГОСТ 34)
  • На площадке проверяются основные кейсы по которым пользователь работает с системой

Если удается поднять такую площадку(что зачастую бывает сделать сложно), и проверить все тест-кейсы по сценариям спецификаций, то с большой вероятностью можно сказать, что система работает ожидаемо и как следствие — не содержит ошибок.

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

Автоматизируем приемочное тестирование


Автоматизация приемочного тестирования сводится к следующим шагам:

  • Написать сценарии приемочных тестов
  • Разработать тесты на основе Selenium
  • Автоматизировать процесс запуска тестов на исполнение после изменения кода в репозитории

Сценарии приемочных тестов


Мы записываем сценарии приемочных тестов в виде use case сценариев в спецификациях. Спецификации разрабатывает аналитик на основе функциональных, пользовательских, нефункциональных и других требований.

Для ведения спецификаций мы используем Atlassian Confluence в связке с Balsamiq Mockups.

Разработка тестов на основе Selenium


Для разработки тестов мы создали собственное решение, которое позволяет:

  • Разрабатывать тесты на основе паттерна PageObject
  • Запускать тесты на различных браузерах
  • В случае ошибки теста получать скриншот, копию html страниц и название тест-кейса

Разработка новых тестов сводится к описанию тестируемой страниц — PageObject и разработке шагов тест-кейса.

Проект с приемочными тестами выглядит так:


Основные компоненты:

  • Common\BasePage.cs — базовый классы для описания PageObject страниц. Содержит вспомогательные методы поиска элементов на странице при помощи различных селекторов.
  • Common\BaseTest.cs — базовый класс для всех приемочных тестов. Содержит логику запуска/останова браузеров для выполнения тестов, логику ожидания завершения всех активных $http запросов клиентского приложения.
  • PageObjects — директория содержит описание страниц клиентского приложения. Сраница Page Object инкапсулирует в себе знания о элементах страницы и о действиях, которые можно выполнить на странице.
  • Директория TestCases — содержит кейсы для выполнения тестов

Тест состоит из шагов — Step(). Шаг может выполнить действие и проверить выполнение некоторого утверждения. Ниже приведен пример теста:

  • Открыть страницу авторизации
  • Войти как администратор
  • Открыть отчет
  • Заблокировать отчет
  • Отредактировать две ячейки «110» и «220»
  • Сохранить изменения
  • Снять блокировку с отчета
  • Убедиться, что в ячейке «ГОУ» рассчиталась сумма по введенным значениям — «110» + «220»

Код теста:


На видео показана работа теста.


Если во время теста произошла ошибка — авторизация не прошла, не открылся отчет и т.д., то в директорию, указанную в app.config, будет сохранен скриншот страницы, название браузера, название теста и html страница с ошибкой.

Определение завершения всех $http запросов AngularJS приложения


Клиентское SPA приложение выполняет запросы к серверу при помощи сервиса $http. Например, при открытии отчета «Суточная ведомость» выполняется асинхронное обращение к серверу. В ответ клиент получает от сервера данные по отчету.

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

Для отслеживания завершения всех $http запросов я использую следующий подход:

  • В клиентском приложении создается переменная, которая содержит число активных $http запросов
  • В сервис $http производится инъекция, которая увеличивает переменную на 1 при отправке запроса и уменьшает переменную на 1 при успешном или неуспешном завершении запроса
  • Selenium проверяет значение этой переменной, чтобы убедиться, что клиент завершил обработку запроса

Запуск приемочных тестов при помощи TeamCity


В качестве сервера непрерывной интеграции мы используем TeamCity.

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

Основные шаги:

  • Очистить директорию сайта от старой сборки
  • Настроить app.config приложения — выполняется конфигурация строк соединения с тестовой БД
  • Собрать проект — запуск MSBuild
  • Остановить IIS
  • Удалить старую тестовую БД
  • Создать новую тестовую БД
  • Скопировать файлы приложения в директорию сайта
  • Запустить IIS
  • Запустить приемочные тесты

Кто пишет приемочные тесты


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

Исходный код


Исходный код тестового приложения доступен на github.

Вывод


Автоматизировать приемочное тестирование можно и нужно. Плюсы данного подхода:

  • Есть гарантии, что в репозитории находится рабочий код, который обязательно соберется, установится на площадку и будет исправно работать по сценариям спецификаций
  • Сокращается время на ручное тестирование — тест пишется один раз и исполняется при каждом изменении кода
  • Сокращается время на регрессионное тестирование
  • Сокращается время на поиск и документирование ошибок — если тест не прошел, то в логах будут записаны шаги воспроизведения и приложен скриншот
  • Сокращается стоимость исправления ошибок — ошибка найденная в офисе будет стоить дешевле ошибки найденной у заказчика

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

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 29

    0
    Насколько я понимаю вы пишете под WD. Как вы используете разные браузеры: создаёте selenium grid или в коде отдельно для каждого браузера прописываете capabilities?
    Вы учитываете особенности работы реализаций драйверов? Нам в своё время пришлось дописать обертку, для того, что бы код выполнялся одинаково во всех браузерах. Так же были случаи, когда js код добавлял атрибут к элементу дерева, после чего селениум проверял этот атрибут быстрее, чем браузер применял изменения и множество других проблем. В общем подавляющее большинство проблем у нас было с Actions и подобными вещами. Интересно послушать, как вы с этим боролись, заранее спасибо.
      0
      >>Насколько я понимаю вы пишете под WD.
      Что такое WD?

      >> Как вы используете разные браузеры: создаёте selenium grid или в коде отдельно для каждого браузера прописываете capabilities?
      Для базового класса теста указан атрибут TestFixture, который передается в конструктор теста. На основе значения этого атрибута создаются различные драйвера. Например, если надо запустить тест под Chrome и IE — надо базовый класс тестов пометить вот так:

      [TestFixture(«Chrome»)]
      [TestFixture(«IE»)]
      public class BaseTest {...}

      Подробнее можно посмотреть в коде. Файл BaseTest.cs и BrowserFactory.cs.

      >> Вы учитываете особенности работы реализаций драйверов?
      Нет. Проверяем стандартно на IE и Chrome. Данных проверок в контексте текущего проекта достаточно.

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

      >> В общем подавляющее большинство проблем у нас было с Actions и подобными вещами. Интересно послушать, как вы с этим боролись, заранее спасибо.
      Честно говоря, пока с такими проблемами не сталкивались.
        0
        Что такое WD?

        WD это webdriver. Но по коду видно что вы всё запускаете локально, это значит у вас агент teamcity висит интерактивно? Почему не используете grid? Раз всю инфраструктуру у вас разворачивает teamcity, то при написании и отладке тестов всё это проделывается вручную?
        И да, исправьте кодировку
        image
          0
          Да, запускается все локально при помощи агента teamcity. В сторону grid честно говоря не смотрели.

          >> при написании и отладке тестов всё это проделывается вручную?
          разработчик и тестировщик отлаживают тесты локально, после чего заливают в репозиторий. Сразу после заливки в репозиторий — запускается агент teamcity.
            0
            Локально запускается агент teamcity? Хардкорно :)
              0
              Видимо не правильно выразился :)
              Есть физическая машина, на который установлен агент. Т.е. запуск идет на удаленной машине, не на машине разработчика.
                0
                Мы друг друга не понимаем наверно. Давайте так. Чтобы написать тест нужно поднять всю обвязку для нормальной работы теста, т.е Поднять приложение, поднять базу и прочее и прочее. Это делается вручную каждый кто хочет написать/поправить тест? Так же, раз уж используете шаги, то почему не выбрали SpecFlow? Мы используем его для написание сценариев.
                  0
                  >> Это делается вручную каждый кто хочет написать/поправить тест?

                  Да. Вся обвязка поднята на машине разработчика локально. Для создания теста разработчик запускает систему у себя на машине и пишет тест.

                  Так же есть виртуальная машина с тестовой площадкой, где поднято все необходимое окружение.
                  Для написания и отладки приемочного теста возможно использовать данную площадку (за исключением сценариев, когда тест «ломает площадку»).

                  Насчет SpecFlow — пока руки не дошли попробовать этот фреймворк в работе.
          +1
          Прошу прощения за столь поздний ответ.
          >> Нет. Проверяем стандартно на IE и Chrome. Данных проверок в контексте текущего проекта достаточно.
          Как показывает мой опыт, наиболее интересные баги воспроизводятся на FF, т.к. V8 у хрома практически не имеет недостатков, то тесты на хром можно мысленно приравнять к тестам проверки логики, а тесты на IE, FF — к тестам на проверку UI. (но это очень формально). Касательно реализаций: далеко не все браузеры умеют делать скриншоты, и capability у них очень сильно отличаются. Например известный баг, что FF на executeScript не может возвращать jQuery объект. И таких особенностей действительно много. Если вы хотите писать действительно кросбраузерные тесты, то допишите еще одну обертку над WD, которая будет учитывать ajax, переходы по фреймам, обрабатывать неподдерживаемые(или некорректно выполняемые) браузером действия. Потому что, когда ваш проект разрастется будет очень тяжело это всё рефакторить.

          В любом случае успехов в вашем начинании, selenium не так прост, как кажется, но если его понять — он станет хорошим союзником в CI.
            0
            Спасибо за доброе слово!

            Обертку для конкретного драйвера, думаю будем создавать по мере возникновения проблем. Обертка по сути будет полноценным Proxy классом над обычным драйвером. Мысль хорошая.
        –6
        короче очередной hello word
          +1
          — кнопку переложили в другой div и 50 тестов отлетело?
          — БД, как я понял, создается одна — т.е. следующие тесты могут быть затронуты изменениями в БД, сделанными предыдущими тестами?
          — если уж Angular — то вроде можно контроллеры юнит-тестить, используете?
            0
            >> — кнопку переложили в другой div и 50 тестов отлетело?
            Классический пример :) ничего не отлетит, т.к. кнопки выбираются при помощи css селектора по id. Тест надо будет править, если поменялся id у кнопки. Даже не сам тест, а описание страницы PageObject.

            >>— БД, как я понял, создается одна — т.е. следующие тесты могут быть затронуты изменениями в БД, сделанными предыдущими тестами?
            Все верно. Пока с необходимостью создавать новую БД при определенном тест-кейсе не сталкивались. Если потребуется, то добавим команду вызова скриптов на удаление/создание БД в базовый класс теста.

            >>— если уж Angular — то вроде можно контроллеры юнит-тестить, используете?
            Можно, но сейчас не используем. Тесты контроллеров это как вы правильно заметили unit-тесты :) Я же хочу указать на пользу именно приемочных тестов. В моей практике не раз было, что unit-тесты отрабатывают, а самые простые пользовательские сценарии сбоят.
              0
              >Классический пример :) ничего не отлетит, т.к. кнопки выбираются при помощи css селектора по id.
              Не, ну про кнопку — это я немного утрировал. Часто ли вы UI меняете, как часто после этого приходится чинить тесты?

              > Я же хочу указать на пользу именно приемочных тестов.
              Как по мне — нужно использовать всё, что может принести пользу, но знать меру. Юнит-тесты проще писать и поддерживать. Автоматизированные тесты UI — сильно тяжелее.

              Короче я бы не был настолько категоричен, что автотесты — это прям must have.
                0
                По факту Page Object файлы правятся не часто. Если все же правка необходима, то в основном все сводится к изменению селектора, что выполняется достаточно просто.

                Насчет использования unit-тестов, согласен с вами — одно другое не исключает. Например, мы в работе используем как unit так и acceptance тесты.

                Про категоричность и «must have» относительно приемочных тестов — тут каждый решает сам, нужно ли использовать в проекте те или иные тесты. Мою точку зрения вы поняли :) я за автоматизацию приемочных тестов, хотя бы их малой части, если нет ресурсов на выполнение такого рода задач в полном объеме.
            +1
            Вместо селениума для ангуляра попробуйте Protractor
              0
              Спасибо. Обязательно посмотрю.
              У нас большинство разработчиков пишут на С#, поэтому Selenium с оберткой для .NET нам ближе.
              +1
              Treshnikov, спасибо за то, что делитесь информацией, а особенно об использовании WebDriver с PageObject'ами.

              Разрешите мне также поделится теми наблюдениями, чем мой подход при работе с WebDriver отличается от вашего:

              Сразу скажу, что у вас хорошее решение со Step(“step step step”) ;)

              1. Я бы сразу разделил код на 3 проекта: отдельно тесты (AcceptanceTesting.Tests), отдельно библиотека с PageObject (AcceptanceTesting.TestModel), отдельно другие библиотечные функции (AcceptanceTesting.Core). – к этому все равно приходят, когда тестов станет много и их захочится разделить на несколько тестовых наборов для запуска параллельно

              2. Для себя я выработал правило: стараться не использовать вебэлементы и другие вызовы вебдрайвера непосредственно в тесте, а использовать только вызовы методов PageObject.
              Т.е. сделать так, чтобы тесты не знали, что они работают с WebDriver.

              Вот, например, этот код я бы оставил не измененным:

              Step("Ввод запроса 'смс автоматизация'",
                     () => googleSearchResultPage = googlePage.EnterSearchText("смс автоматизация"));
              


              А вот этот бы заменил

              Step("Первая ссылка должна содержать адрес sms-automation.ru",
              () =>
              {
                    var href = googleSearchResultPage.FirstLink.GetAttribute("href");
                    Assert.AreEqual(href, "http://www.sms-automation.ru/");
              });
              


              на

              Step("Первая ссылка должна содержать адрес sms-automation.ru",
              () =>
              {
                    var href = googleSearchResultPage.GetFirstLink();
                    // или 
                    // var href = googleSearchResultPage.GetAllLinks().First();
                    Assert.AreEqual(href, "http://www.sms-automation.ru/");
              });
              


              Спасибо вам еще раз, за то, что делитесь знаниями и хорошими подходами!

              Минутка самопиара:
              А посмотрите ещё мой Page Recorder, который может ускорить процесс создания PageObject классов.
                +1
                Ловите плюс в карму :)

                Насчет разделения тестов и классов page-object на проекты — думаю это уже более косметический штрих, т.к. проекты будут знать друг о друге.
                Вместо проектов мы группируем файлы по директориям внутри одного проекта. Не исключаю, что в итоге придем к вашему решению.

                >> Для себя я выработал правило: стараться не использовать вебэлементы и другие вызовы вебдрайвера непосредственно в тесте, а использовать только вызовы методов PageObject.

                Согласен с вами на все 100%. Примеры, которые заливал на github были написаны на «скорую руку». Боевые классы page-object инкапсулируют в себе знания о драйвере, а наружу выставляют только свойства и методы.

                Page Recorder посмотрю, выглядит заманчиво.
                0
                А у Вас надобности в создании своего DSL (domain specific language) для тестов не было? Что бы абстрагироваться от кода и писать в бизнес терминах? Мы так делали. Очень удобно — программисты раз написали DSL (пишется очень легко — по сути у нас нужна была поддержка pageObject на уровне языка, что бы их не создавать в коде) и дальше QA пишут тестовый скрипт, который не содержит в себе никаких лишних строк — только бизнес действия (плюс в верху для всех тестовых скриптов одинаковая «шапка» импорта).
                  0
                  Написал ответ вам ниже.
                  +1
                  Звучит здорово! Хотелось бы взглянуть на пример.

                  Насчет DSL — немного смущает еще один уровень абстракции, о котором так же надо думать.
                  Работа с page object на текущем уровне тестирования для нас пока достаточна.

                  В комментарии выше мне уже указывали на SpecFlow. Складывается впечатление, что это уже немного другой уровень восприятия задачи тестирования как таковой и похоже мы до этого уровня пока не дошли :)
                    +1
                    import pageobject.*
                    import pageobject.properties.*
                    import pageobject.search.*
                    import pageobject.selector.*
                    import pageobject.tabs.*
                    
                    import static pageobject.PageObjectFactory.getPage
                    
                    def authorLogin = "aaa"
                    def authorPassword = "bbb"
                    def firstApproverLogin = "ccc"
                    def firstApproverPassword = "ddd"
                    def secondApproverLogin = "eee"
                    def secondApproverPassword = "fff"
                    def firstApproverComment = "ggg"
                    def regNumberbudget = "kkk"
                    
                    def sleepInterval = 20000
                    
                    // Вход в систему под Автором
                    loginLogoutPage.login(authorLogin, authorPassword)
                    // Вызов меню Создать Договор бюджета
                    menuBarPage.pressFileCreateMenuItem(MenuBarPage.FileCreateMenuItem.CONTRACT)
                    // Заполнение обязательных полей карточки
                    //1. Добавление контента
                    contractPage.selectFile("C:\\Users\\lll\\Desktop\\Архивная справка_скан.PDF")
                    // Выбор бюджета
                    //1. Нажать кнопку выбор бюджета
                    contractPage.pressSelectBudget()
                    //2. Страница селектора бюджетов, Ввести значение в поле номер
                    selectorBudgetPage.inputRegNum(regNumberbudget)
                    //3. Нажать кнопку поиск
                    selectorBudgetPage.pressSearch()
                    //4. Добавить первый результат поиска к выбранным
                    selectorBudgetPage.clickFirstResult()
                    //5. Нажать кнопку выбрать
                    selectorBudgetPage.pressSelectButton()
                    

                    Написано на Groovy.
                    Тут объекты loginLogoutPage, menuBarPage, contractPage и т.д. фактически являются PageObject и определены как часть языка (с помощью простого конфига для IDEA будут подсвечиваться в IDE с поддержкой autocomlite). Т.е. в скрипте их создавать не нужно. Из за того, что это свой DSL, со своими объектами языка, скрипт имеет своё расширение. (в конфиге для IDE как раз и прописываются правила обработки файлов этого расширения). Блок с импортами во всех скриптах одинаков и фактически является копипастой, но вынести в отдельный файл не получилось.
                    Работа с этим скриптов проста — сначала пишется test case, потом после каждой строчки test case пишется на DSL код. Фактически получается простое соотношение — строчка test case равна строчке на DSL. Ничего лишнего. Пример этого виден в скрипте — комментарии как раз и являются test case.
                      +1
                      Я понял вашу идею — выглядит очень не плохо. При этом похоже на наш подход с единственным отличием — у вас страницы представлены статическими объектами и при написании тестов пользователь не думает о времени жизни страницы и пишет сценарий последовательно по шагам.

                      Соглашусь, что ваш код читается легче :)

                      protected override void Setup()
                      {
                          dailyListPage = new LoginPage(Driver)
                              .LoginAsAdmin()
                              .OpenDailyList();
                      }
                      
                      [Test]
                      public void DailyList_Test_Parameter_Calculation()
                      {
                          var random = new Random();
                          var v110 = random.Next(100);
                          var v220 = random.Next(100);
                          var gou = v110 + v220;
                      
                          Step("Блокировать документ на редактирование",
                              () => dailyListPage.LockButon.Click());
                      
                          Step("Отредактировать параметр 110 и 220 за третий час",
                              () =>
                              {
                                  dailyListPage.PowerTable.EditCell(3, 2, v110.ToString());
                                  dailyListPage.PowerTable.EditCell(3, 3, v220.ToString());
                              });
                      
                          Step("Сохранить изменения",
                              () => dailyListPage.SaveButon.Click());
                      
                          Step("Измененные ячейки отмечены меткой \"есть изменения\",
                              () => (dailyListPage.PowerTable.CellMarkedAsChanged(3, 2) && dailyListPage.PowerTable.CellMarkedAsChanged(3, 3)).ShouldBeTrue());
                      
                          Step("Разблокировать документ на редактирование",
                              () => dailyListPage.LockButon.Click());
                      
                          Step("Проверка колонки ГОУ = 110 + 220",
                              () => dailyListPage.PowerTable.Rows[3].Cells[1].Value.ShouldEqual(gou.ToString()));
                      }
                      
                        0
                        При этом похоже на наш подход с единственным отличием — у вас страницы представлены статическими объектами и при написании тестов пользователь не думает о времени жизни страницы и пишет сценарий последовательно по шагам.

                        Да, у нас так получилось, что большинство PageObject не нужно было каждый раз заново создавать, но в паре мест, где PageObject должен знать в контексте какой странице он применён, приходилось определять эти PageObject через переменные, e.g.:
                        def menu = contractPage.getMenu()
                        
                    –1
                    Тоже сейчас делаю свой проект с Selenium + JavaMail. У меня не все так глобально, как у вас, но все же. Моя программа работает для автоматической регистрации на классы в моем университете :) Tracking почты на получение сообщения от университета, парсинг сообщения и запуск автоматической регистрации через Selenium, использую FireFox драйвер, т.к. с HtmlDriver'ом проблемы. Он не определает xss путь textField'а ("//*[@type='TEXT']") в режиме HtmlDriver, только в Firefox. Это осталось для меня загадкой. А так подкреплюсь вашим опытом, может что нибудь да оптимизирую у себя.

                    Так же подумываю перенести всю эту ахинею на сервер. Кажется видел, что у Selenium'а есть поддержка JavaScript
                      0
                      Заинтересовалась статьей из-за названия:
                      Selenium + .NET Web Api + AngularJs
                      А в итоге чуток Selenium упомянут, показана архитектура согласно модели PageObjects, а про то, как натравить webDriver на веб-приложение, написанное с использованием AngularJs — как искать WebElement-ы, например — не написано почти ничего.

                      Я верю, что у вас эта экспертиза есть. поделитесь, пожалуйста, светом знаний!

                      Например, у меня не получается узнать, какой чекбокс выбран. Чекбоксы выглядят вот так:
                      <span radio="Model.application.type" value="desired_key_word" class="ng-isolate-scope">
                      <span class="radio" style="cursor: pointer; background-position: 0px -57px;" data-styled="1"></span> 
                      <span class="radio-label" style="cursor: pointer; background-position: 0px -57px;" ng-transclude="">
                      <span class="ng-scope">Лейбл чекбокса, название опции</span></span></span>
                      


                      desired_key_word — это value чекбокса, которое я хотела бы вытащить у того чекбокса, который выбран, и сравнить с ожидаемым.

                      Ломаю голову, как использовать CSSselector чтобы найти чекбокс в состоянии isChecked и узнать значение его value.
                      Пробую так:
                      var checkboxElement = _webDriver.FindElement(By.CssSelector("span[radio='Model.application.type']"));
                      var s = checkboxElement.GetAttribute("value");
                      Assert.AreEqual("desired_key_word", s);
                      

                      и другие варианты селекторов пробовала, ну ни как не выходит. Все время ошибка «элемент не найден».

                      Я буду вам безмерно признательна за статью, которая на примерах покажет, как писать тесты с Selenium WebDriver для приложений, написанных с AngularJS!

                      А пока посмотрю примеры ваших тестов на гитхабе. Спасибо за них!
                        0
                        Разобралась со своим кодом. работает так:
                        var checkbox = _webDriver.FindElements(By.CssSelector("[radio='Model.application.type']"))[1];
                        var s = _webDriver.ExecuteJavaScript<string>("return angular.element(arguments[0]).scope().Model.application.type;", checkbox);
                        Assert.AreEqual("desired_key_word", s);
                        


                        Посмотрела примеры ваши.
                        Нашла полезными следующие методы базового класса страницы:
                        public object ExecuteJavaScript(string javaScript, params object[] args)
                        {
                        var javaScriptExecutor = (IJavaScriptExecutor)Driver;
                        return javaScriptExecutor.ExecuteScript(javaScript, args);
                        }
                        public void ScrollToElement(IWebElement element)
                        {
                        ExecuteJavaScript("arguments[0].scrollIntoView(true);", element);
                        }
                        public void ScrollToTop()
                        {
                        ExecuteJavaScript("window.scrollTo(0,0);");
                        }
                        


                        Копаюсь в направлении того, чтобы находить веб-элементы ява скриптом.

                        Коллеги подсказали, что AngularJS придумали как раз для увеличения тестируемости веб-приложений. Пока звучит сомнительно, надо почитать документацию к нему. А вы как думаете? Если есть преимущество приложения с AngularJS в плане тестирования, то в чем же оно?
                          0
                          Ох… только решил авторизоваться на хабре, увидел ваши комментарии.
                          Очень рад, что мои наработки вам пригодились!

                      Only users with full accounts can post comments. Log in, please.