[Из песочницы] Тестируем Web UI на F# и canopy
В процессе UI тестирования своего рабочего проекта на C# и selenium, я задумался о том, как будут выглядеть тест сценарии на одном из функциональных языков. Мой выбор пал на F#. Поискав, я наткнулся на очень интересный фреймворк под названием canopy, который базируется на всем известном selenium и полностью реализованном на языке F#. С первых же строк кода он произвел на меня впечатление своей простотой и минимализмом синтаксиса, который позволяет упрощать сложные вещи.
В качестве примера давайте рассмотрим простейший случай теста с главной страницы сайта. Для запуска необходимо установить nuget-пакет canopy и скачать webdriver для своего браузера.
//these are similar to C# using statements
open canopy
open runner
open System
//start an instance of the firefox browser
start firefox
//this is how you define a test
"taking canopy for a spin" &&& fun _ ->
//this is an F# function body, it's whitespace enforced
//go to url
url "http://lefthandedgoat.github.io/canopy/testpages/"
//assert that the element with an id of 'welcome' has
//the text 'Welcome'
"#welcome" == "Welcome"
//assert that the element with an id of 'firstName' has the value 'John'
"#firstName" == "John"
//change the value of element with
//an id of 'firstName' to 'Something Else'
"#firstName" << "Something Else"
//verify another element's value, click a button,
//verify the element is updated
"#button_clicked" == "button not clicked"
click "#button"
"#button_clicked" == "button clicked"
//run all tests
run()
printfn "press [enter] to exit"
System.Console.ReadLine() |> ignore
quit()
Не вооруженным глазом видно, что код очень простой и читабельный. После запуска программа выводит краткий отчет с результатами.
Но на этом еще не все. Хочу рассказать про основные плюшки для работы полноценного UI тестирования.
Есть возможность тестирования с замедлением и выделением элементов, с которыми работает тест. Все что нужно — после названием теста добавить еще один знак амперсант (&).
"taking canopy for a spin" &&&& fun _ ->
Теперь мы видим элементы с которыми работает тест.
Если нам нужно специально выделить какой -либо элемент, используем функцию
highlight ".btn"
Очень просто делать скрины можно с помощью функции: screenshot. Все, что нужно указать путь и название скриншота
let path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\canopy\"
let filename = DateTime.Now.ToString("MMM-d_HH-mm-ss-fff")
screenshot path filename
Можно усложнить и улучшить наш тест, добавив функцию, которая при любом не пройденном тесте делает скриншот:
onFail (fun _ ->
let pathToReports = __SOURCE_DIRECTORY__ + @"\canopy\"
let filename = System.DateTime.Now.ToString("MMM-d_HH-mm-ss-fff")
screenshot pathToScreens filename
|> ignore
)
В результате при падении какого — либо из тестов добавляется скриншот в папку «canopy», расположенную в корне проекта.
Еще одну интересную особенность можно обнаружить при формировании отчета. Все, что от нас требуется — добавить использование реализованного html репортера. После запуска мы видим, что отчет сформировался в удобном формате HTML, в дополнении выводятся скриншоты браузера для проваленных тестов. Для автоматического сохранения отчета добавляем еще пару строк кода:
let liveHtmlReporter = reporter :?> LiveHtmlReporter
liveHtmlReporter.reportPath <- Some pathToReports
Для запуска javascript скрипта используем функцию js
//give the title a border
js "document.querySelector('#title').style.border = 'thick solid #FFF467';"
Для симулирования нажатия клавиши клавиатуры используем функкцию press tab, press enter, press up и т.д. Это лишь малая часть интересных функций для выполнения сложной работы, показывающие сильные стороны минимализма фреймворка.
Итого, что мы имеем. Фреймворк очень прост в использовании, что позволяет писать простые, лаконичные и читабельные тесты, понятные разработчику любого уровня. Используя canopy, можно строить довольно удобные и содержательные отчеты, как по пройденным тестам, так и по проваленным.