- PVSM.RU - https://www.pvsm.ru -
Привет, привет! Ну что же, пришло время заключительной части, в которой я приведу пример несложных тестов, написанных с применением врапперов из предыдущих частей статьи. Как и обещал, открываю публичный доступ к работающей версии фреймфорка (см. ссылки).
Часть 1: Введение [1]
Часть 2.1: Selenium API wrapper — Browser [2]
Часть 2.2: Selenium API wrapper — WebElement [3]
Часть 3: WebPages — описываем страницы [4]
Часть 4: Наконец-то пишем тесты [5]
Публикация фреймворка [6]
И так, в качестве учебного материала мы напишем несколько тестов переводчика Google. Я ни в коем случае не собираюсь делать какое-либо тестовое покрытие, поэтому я придумал 4 сценария:
Главная страница довольно простая — у нас есть поле ввода и результат перевода. Для выполнения перевода даже не обязательно нажимать кнопку «Перевести». Описание страницы получилось вот таким:
namespace Autotests.WebPages.Root
{
public class Index : PageBase
{
#region Elements
private static readonly WebElement SourceEdit = new WebElement().ById("source");
private static readonly WebElement ResutlText = new WebElement().ById("result_box");
private static readonly WebElement ClearButton = new WebElement().ById("clear");
private static readonly WebElement WebsiteTranslatorLink = new WebElement()
.ByAttribute(TagAttributes.Href, Pages.Manager.Websites.Index.BaseUrl.ToString(), exactMatch: false);
#endregion
public void Open(string from, string to)
{
Contract.Requires(from != to);
var url = new Uri(string.Format("{0}#{1}/{2}/", BaseUrl, from, to));
Navigate(url);
}
public string SourceText
{
get { return SourceEdit.Text; }
}
public string ResultText
{
get { return ResutlText.Text; }
}
public string Translate(string text)
{
SourceEdit.Text = text;
if (!string.IsNullOrEmpty(text))
{
Contract.Assert(WaitHelper.SpinWait(() => !string.IsNullOrEmpty(ResutlText.Text), TimeSpan.FromSeconds(10)));
}
return ResultText;
}
public void Clear()
{
Contract.Assert(ClearButton.Exists(10));
ClearButton.Click(useJQuery: false);
}
public void OpenWebsiteTranslator()
{
WebsiteTranslatorLink.Click(useJQuery: false);
}
}
}
Я описал 4 элемента, три из них находится по id, а четвертый — по вхождению ссылки в атрибут href. Класс унаследован от PageBase, код которого приводился в предыдущей статье и доступен в паблике. Перегруженный метод Open умеет открывать переводчик с указанием языков, например en-ru. Ну а также класс содержит весь функционал, который понадобился в рамках автоматизации описанных ранее сценариев.
Также приведу описание второй страницы — переводчика сайтов:
namespace Autotests.WebPages.Root.Manager.Website
{
public class Index : PageBase
{
}
}
Класс пустой, поскольку в тестах требуется проверить лишь то, что страница открылась, никаких действий на ней мы производить не будем.
Для начала напишем базовый класс:
namespace Autotests.Suites
{
[TestClass]
public abstract class SuiteBase
{
public TestContext TestContext { get; set; }
[TestInitialize]
public void TestInitialize()
{
Browser.Start();
}
[TestCleanup]
public void TestCleanup()
{
Browser.Quit();
}
}
}
Класс определяет предусловия и постусловия для каждого теста, в данном случае — открытие и закрытие браузера. Замечу, что открытие делать не обязательно, браузер откроется при первом доступе к нему. Кроме TestInitialize и TestCleanup существуют еще и ClassInitialize и ClassCleanup, которые тоже выполняют предусловия и постусловия, но для группы тестов из одного класса, когда они запущены вместе (последовательно). Также определен TestContext, который смогут использовать все тесты, например, для прикрепления файлов к результатам.
Ну и, наконец-то, код наших тестов:
namespace Autotests.Suites
{
[TestClass]
public class GoogleTranslateTests : SuiteBase
{
[TestMethod]
public void TranslateText()
{
#region TestData
const string languageFrom = "en";
const string languageTo = "ru";
const string textEn = "hello";
const string textRu = "привет";
#endregion
Pages.Index.Open(languageFrom, languageTo);
var result = Pages.Index.Translate(textEn);
Assert.AreEqual(textRu, result,
string.Format("{0} != {1}.", textRu, result));
}
[TestMethod]
public void CheckJavaScriptEscape()
{
#region TestData
const string languageFrom = "en";
const string languageTo = "en";
const string javascript = "alert(1);";
#endregion
Pages.Index.Open(languageFrom, languageTo);
var result = Pages.Index.Translate(javascript);
Assert.AreEqual(javascript, result,
"JavaScript was executed.");
}
[TestMethod]
public void ClearSourceText()
{
Pages.Index.Open();
Pages.Index.Translate(RandomHelper.RandomString);
Pages.Index.Clear();
Assert.IsTrue(string.IsNullOrEmpty(Pages.Index.SourceText),
"Source text was not cleared.");
}
[TestMethod]
public void NavigateWebsiteTranslator()
{
Pages.Index.Open();
Pages.Index.OpenWebsiteTranslator();
Assert.IsTrue(Browser.Url.Contains(Pages.Manager.Websites.Index.BaseUrl),
"WebsiteTranslator was not opened.");
}
}
}
Замечу, что один тест проверяет одно логическое действие. Тестовые данные находятся в тестах, но вы можете хранить их где угодно — в xml, в базах данных и любых других хранилищах. Так же дам ссылку на DDT How to: Create a data-driven unit test [7]
Спасибо всем, кто прочитал статью, задавал вопросы и высказывал предложения! На этом мой рассказ окончен, и я сам очень рад, что удалось довести дело до конца и рассказать об автоматизированном тестировании веб-приложения на Selenium C# в рунете, ведь информации и примеров на русском языке пока что очень мало. Удачи!
Автор: natexriver
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/testirovanie/35606
Ссылки в тексте:
[1] Часть 1: Введение: http://habrahabr.ru/post/178321/
[2] Часть 2.1: Selenium API wrapper — Browser: http://habrahabr.ru/post/180047/
[3] Часть 2.2: Selenium API wrapper — WebElement: http://habrahabr.ru/post/180357/
[4] Часть 3: WebPages — описываем страницы: http://habrahabr.ru/post/180705/
[5] Часть 4: Наконец-то пишем тесты: http://habrahabr.ru/post/181558/
[6] Публикация фреймворка: https://autotests.codeplex.com/
[7] How to: Create a data-driven unit test: http://msdn.microsoft.com/en-us/library/ms182527.aspx
Нажмите здесь для печати.