Вот вы, значит, сидите себе спокойно, кофе попиваете, на кнопочки кликаете, и тут к вам залетает ваш взмыленный руководить проекта/начальник/тим лид или генеральный директор и говорит:
«Нам нужна автоматизация тестирования, а то без нее никак, все развалится, а будет – дадим тебе синьйора с бонусами!».
Ну, значит, сидите вы после этого замотивированный толи негативно, толи позитивно, в общем – неважно, но важно то, что работу то нужно работать.
Ну, значит, оглянулись вы по сторонам, а вокруг на проекте – Дикий Запад, в кого не плюнь все на C# и .NET пишут. Да, и вы вспомнили, что когда-то толи на C# толи на ASP.NET что-то делали. И совсем недавно какой-то слух прошел, что вышел Selenium Webdriver 2, который, говорят, лучше первой версии и все на нем значит, автоматизацию и готовят.
Тут вы забиваете а Гуугл заклинание:
selenium webdriver c# tutorial
И получаете страницу вполне релевантных результатов, надеясь найти там хорошие примеры по автоматизации.
Вот самая первая ссылка вполне подходит:
http://www.theautomatedtester.co.uk/tutorials/selenium/selenium_two_csharp_nunit.htm
В этой статье показывается и рассказывается как Selenium подключить и первый тест написать. Все бы было хорошо,
но! Обратите внимание на то, что пример этот показывает как Селениум подключить и гугл автоматизировать, но этот пример не показывает как правильно нужно, тесты писать.
Давайте рассмотрим этот пример теста более детально:
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
using NUnit.Framework;
namespace Selenium.Two.DotNetExample
{
[TestFixture]
public class Test_Google
{
IWebDriver driver;
[SetUp]
public void Setup()
{
driver = new InternetExplorerDriver();
}
[TearDown]
public void Teardown()
{
driver.Quit();
}
[Test]
public void TestSearchGoogleForTheAutomatedTester()
{
//Navigate to the site
driver.Navigate().GoToUrl("http://www.google.co.uk");
//Find the Element and create an object so we can use it
IWebElement queryBox = driver.FindElement(By.Name("q"));
//Work with the Element that's on the page
queryBox.SendKeys("The Automated Tester");
queryBox.SendKeys(Keys.ArrowDown);
queryBox.Submit();
//Check that the Title is what we are expecting
Assert.True(driver.Title.IndexOf("The Automated Tester") > -1);
}
}
}
Вот вы все подключили, и NUnit с Webdriver скачали:
И даже тест в NUnit запустили, и он даже прошел, но:
NUnit вам показывает какую-то фигню в ошибке:
Selenium.Two.DotNetExample.Test_Google.TestSearchGoogleForTheAutomatedTester:
Expected: True
But was: False
Значит, вы искали «The Automated Tester», а получили что-то другое? Отлично. А что? А что вы еще хотели от Assert.True, который служит для проверки булевых значений, а не для строк?
//Check that the Title is what we are expecting
Assert.True(driver.Title.IndexOf("The Automated Tester") > -1);
На этом можно было бы не заострять внимание, но если бы вы знали, сколько раз встречаешь в реальном коде именно такое…
Давайте сразу же исправим:
//Check that the Title is what we are expecting
StringAssert.Contains("The Automated Tester", driver.Title);
И получим следующий результат после теста:
Тест продолжает безнадежно валится, но давайте уже его допилим, и без лишних излишеств очень топорно поставим Sleep на 2 секунды. Что, конечно же, является огромной ошибкой, но для примера сойдет. Ведь пример – это игрушечный код.
System.Threading.Thread.Sleep(2000);
//Check that the Title is what we are expecting
StringAssert.Contains("The Automated Tester", driver.Title);
Да, сейчас NUnit выдает более понятную ошибку:
Selenium.Two.DotNetExample.Test_Google.TestSearchGoogleForTheAutomatedTester:
Expected: String containing "The Automated Tester"
But was: "the automated tester - Поиск в Google"
И эта ошибка говорит, что, с учетом регистра символов, строка "The Automated Tester" не была найдена в строке "the automated tester - Поиск в Google".
Можете сами попробовать. Сейчас Google, при поиске, помещает в свой заголовок поисковую фразу в нижнем регистре символов. Я считаю, что это бага, и обязательно напишу репорт в Гуугл.
А вот теперь давайте подумаем над следующим вопросом:
Сколько в этом тесте тестового кода? То есть, кода, который что-то тестирует?
Сходу можно ответить: Да ты что, тут весь код тестовый, это же тест!
Да?! А давайте этот тест немного порефакторим:
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
using NUnit.Framework;
namespace Selenium.Two.DotNetExample
{
[TestFixture]
public class Test_Google
{
IWebDriver driver;
[SetUp]
public void Setup()
{
driver = new InternetExplorerDriver();
}
[TearDown]
public void Teardown()
{
driver.Quit();
}
public class GoogleSearchPage
{
IWebDriver drv;
string DefaultUrl = "http://www.google.co.uk";
public IWebElement QueryBox { get { return drv.FindElement(By.Name("q")); } }
public GoogleSearchPage(IWebDriver drv)
{
this.drv = drv;
}
public void Show()
{
Show(DefaultUrl);
}
public void Show(string url)
{
//Navigate to the site
drv.Navigate().GoToUrl("http://www.google.co.uk");
}
public void Search(string searchPhrase)
{
Show();
//Work with the Element that's on the page
QueryBox.SendKeys("The Automated Tester");
QueryBox.SendKeys(Keys.Enter);
System.Threading.Thread.Sleep(2000);
}
}
[Test]
public void TestSearchGoogleForTheAutomatedTester()
{
string googleSearchPhrase = "The Automated Tester";
var googlePage = new GoogleSearchPage();
googlePage.Search(googleSearchPhrase);
StringAssert.Contains(googleSearchPhrase, driver.Title);
}
}
}
Что случилось?
Появился класс, который скрыл в себе все технические детали теста. Теперь этот класс можно использовать повторно и вынести в отдельный файл, чтобы глаза не мозолил.
Теперь на тест не содержит деталей даже о том, что мы используем Selenium. Там две строчки кода, которые просто объявляют переменные, одна строчка действия и одна проверка.
Ну, хорошо, а что если нам нужно написать второй тест кейс?
Тогда наш код будет выглядеть так:
[Test]
public void TestSearchGoogleForTheAutomatedTester()
{
string googleSearchPhrase = "The Automated Tester";
var googlePage = new GoogleSearchPage(driver);
googlePage.Search(googleSearchPhrase);
StringAssert.Contains(googleSearchPhrase, driver.Title);
}
[Test]
public void TestSearchGoogleForTheDZisIsATest()
{
string googleSearchPhrase = "DZis is a test";
var googlePage = new GoogleSearchPage(driver);
googlePage.Search(googleSearchPhrase);
StringAssert.Contains(googleSearchPhrase.ToLower(), driver.Title.ToLower());
}
Вместо вот этого:
[Test]
public void TestSearchGoogleForTheAutomatedTester()
{
//Navigate to the site
driver.Navigate().GoToUrl("http://www.google.co.uk");
//Find the Element and create an object so we can use it
IWebElement queryBox = driver.FindElement(By.Name("q"));
//Work with the Element that's on the page
queryBox.SendKeys("The Automated Tester");
queryBox.SendKeys(Keys.ArrowDown);
queryBox.Submit();
//Check that the Title is what we are expecting
Assert.True(driver.Title.IndexOf("The Automated Tester") > -1);
}
[Test]
public void TestSearchGoogleForTheDZisIsATest()
{
//Navigate to the site
driver.Navigate().GoToUrl("http://www.google.co.uk");
//Find the Element and create an object so we can use it
IWebElement queryBox = driver.FindElement(By.Name("q"));
//Work with the Element that's on the page
queryBox.SendKeys("DZis is a test");
queryBox.SendKeys(Keys.ArrowDown);
queryBox.Submit();
//Check that the Title is what we are expecting
Assert.True(driver.Title.IndexOf("DZis is a test") > -1);
}

Было бы глупо, если бы я был против простых примеров кода автоматизированного тестирования.
Но, я хочу подчеркнуть то, что код в примерах сознательно упрощен. Единственна я цель примера кода c использованием Selenium – это показать то, как вы можете кликать на кнопочки и вводить текст. Но не, рассказать о том, как вам нужно правильно писать тесты.
Это приемлемо, когда у вас в одном тесте используются, и детали о том как Селениум должен найти кнопку, и сколько времени подождать и какой идентификатор у чекбокса…
Но, когда у вас таких тестов 300? Что будет, если идентификатор одного элемента изменится, и чтобы все исправить вам будет необходимо перелопать 300 тестов? И это вместо того чтобы вынести все в отдельное место, в отдельный класс. Ведь тогда вам будет необходимо изменить этот идентификатор лишь в одном месте.
Используйте примеры на здоровье, но не забывайте, что примеры кода – это игрушечный код.