Возможность автоматизированного тестирования под несколькими браузерами.
- Подготовка проекта.
- Описание роботы c Selenium.
- Пример 1.
- Пример 2.
- Тестирование под несколькими браузерами.
1. Подготовка проекта.
И так приступим. К примеру, у нас есть webaplplication, который нам нужно протестировать, при чём протестировать с клиентской стороны. В этой ситуации конечно ни что не заменит труд тестировщика, но есть несколько уловок, которые позволят уменьшить монотонный труд.
Для этого устанавливаем Gallio и создаем проект в VS с MbUnit тестами.
Теперь попытаемся интегрировать селениум в наш проект.
Устанавливаем Java.
Качаем Selenium RC. Из скачанного нам нужно всего две библиотеки selenium-remote-control-1.0.3.zip\selenium-dotnet-client-driver-1.0.1\ThoughtWorks.Selenium.Core.dll и \selenium-remote-control-1.0.3.zip\selenium-server-1.0.3\ selenium-server.jar
Добавляем в проект эти две библиотеки.
Добавляем для этого проекта референс на ThoughtWorks.Selenium.Core.dll
Потом добавляем следующий класс, который будет подымать селениум сервер:
using System; using System.Diagnostics; using MbUnit.Framework; namespace EHandelSeleniumTest { [TestFixture] public class SeleniumTestingSetup : IDisposable { [SetUp] public void Setup() { seleniumServerProcess = new Process(); seleniumServerProcess.StartInfo.FileName = "java"; //относительный путь к библиотеке seleniumServerProcess.StartInfo.Arguments ="-jar ../../Tools/Selenium/selenium-server/selenium-server.jar -port " + ServerPort; seleniumServerProcess.Start(); } private int _serverPort; public int ServerPort { get { if (_serverPort<=0) { return 4444; } return _serverPort; } set { _serverPort = value; } } public bool IsStarted() { return seleniumServerProcess != null; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (false == disposed) { if (disposing) DisposeOfSeleniumServer(); disposed = true; } } private void DisposeOfSeleniumServer() { if (seleniumServerProcess != null) { try { seleniumServerProcess.Kill(); bool result = seleniumServerProcess.WaitForExit(10000); } finally { seleniumServerProcess.Dispose(); seleniumServerProcess = null; } } } private bool disposed; private Process seleniumServerProcess; } }Теперь добавляем класс, который будет базовым для всех тестов:
using System; using System.Text; using System.Threading; using MbUnit.Framework; using Selenium; namespace EHandelSeleniumTest { [TestFixture] public class SeleniumBase { //адрес тестируемого сайта. private string sitePath = "http://www.google.com/"; //тестируемый броузер. public string Browser = "firefox"; protected ISelenium selenium; private StringBuilder VerificationErrors; SeleniumTestingSetup seleniumServer = new SeleniumTestingSetup(); [SetUp] public void SetupTest() { seleniumServer.Setup(); selenium = new DefaultSelenium("localhost", seleniumServer.ServerPort, "*" + Browser, sitePath); selenium.Start(); VerificationErrors = new StringBuilder(); } [TearDown] public void TeardownTest() { try { selenium.Stop(); } catch (Exception) { // Ignore errors if unable to close the browser } Assert.AreEqual("", VerificationErrors.ToString()); seleniumServer.Dispose(); } } }
2.Описание роботы с Selenium.
Теперь ознакомимся с тулзой для автоматизирование тестирование Selenium Selenium для этого ставим расширение для Firefox
После этого у вас появиться возможность записывать тест сценарии. На сайте проекта есть видео, как начать работать с этой тулзой. В двух словах это выглядит так:
После установки плагина для FF у вас появиться следующий пункт в меню:
Выбираем этот пункт и у нас появиться следующее окно
жмем кнопку записи и с этого момента плагин будет записывать наши действия на сайте с последующей возможностью воспроизвести их.
3. Пример 1.
И так, давайте протестируем Google.com и попытаемся найти документацию для Selenium
Открываем Google.com, потом ставим селениум на запись и вводим в поиск «Selenium документация», жмем поиск.
У нас примерно будет следующий результат после всех наших действий.
Теперь нам нужно всё это экспортировать в наши тесты.
Экспортируем тест кейс в C# файл.
У нас получиться примерно такой код:
using System; using System.Text; using System.Text.RegularExpressions; using System.Threading; using NUnit.Framework; using Selenium; namespace SeleniumTests { [TestFixture] public class Test { private ISelenium selenium; private StringBuilder verificationErrors; [SetUp] public void SetupTest() { selenium = new DefaultSelenium("localhost", 4444, "*chrome", "http://change-this-to-the-site-you-are-testing/"); selenium.Start(); verificationErrors = new StringBuilder(); } [TearDown] public void TeardownTest() { try { selenium.Stop(); } catch (Exception) { // Ignore errors if unable to close the browser } Assert.AreEqual("", verificationErrors.ToString()); } [Test] public void TheTest2Test() { selenium.Open("/"); selenium.Type("q", "Selenium документация"); selenium.Click("btnG"); } }Добавляем этот класс к нашему проекту.
Наследуемся от SeleniumBase класса, после этого удаляем весь мусор, оставив только сам метод с тестом TheTest2Test() переименовываем, и приводим в порядок:
namespace TestProject { [TestFixture] public class UnitTest1 : SeleniumBase { [Test] public void TheGoogleTest() { selenium.Open("/"); selenium.Type("q", "Selenium документация"); selenium.Click("btnG"); selenium.WaitForPageToLoad("1000"); Assert.IsTrue(selenium.IsTextPresent("Selenium")); } } }В тест мы добавили маленький таймаут, чтоб дать возможность странице загрузиться и проверку на вхождение поискового слова в ответе сайта.
4.Пример 2.
Для второго примера я создал маленькую вебапликацию которая делает сложение двух чисел и выводит результат.
И так запускаем вебапликацию потом включает Selenium на запись.
Теперь продолжаем роботу с аппликацией. Вставляем операнд 1,2 и жмем кнопку.
Экспортируем тест в С# и добавляем проверку результата, не забываем сменить адрес сайта в SeleniumBase.
[Test] public void TheSumTest() { selenium.Open("/Default.aspx"); selenium.Type("operant1", "3"); selenium.Type("operant2", "2"); selenium.Click("button1"); selenium.WaitForPageToLoad("30000"); Assert.AreEqual(int.Parse(selenium.GetText("result")),5); }Спасибо ASP .NET 4.0, а точнее новой фиче как ClientId для контролов. Теперь мы всегда можем знать id элемента и найти его намного проще. Для других версий ASP пришлось бы использовать XPath чтоб найти элемент, так как id элемента динамически перегененрировалось.
И наш пример напоминал бы что такое
[Test] public void TheSumTest() { selenium.Open("/Default.aspx"); selenium.Type("//input[@id='operant1']", "3"); selenium.Type("//input[@id='operant2']", "2"); selenium.Click("//input[@id='button1']"); selenium.WaitForPageToLoad("30000"); Assert.AreEqual(int.Parse(selenium.GetText("//span[@id='result']")), 5); }Мы запросто можем добавить всевозможные проверки или тело теста в цикл.
Представим, что это была не простая задачка на суммирование двух чисел, а более сложные вычисление. Теперь делая изменения в аппликации нам не придётся перепроверять все места, где может возникнуть ошибка, а всего лишь перезапустить тест.
5. Тестирование под несколькими браузерами одновременно.
Если у вас возникло желание протестировать сразу под несколькими браузерами, то нам нужно будет пойти на некоторые ухищрение.
Есть два пути - лёгкий (не совсем корректный) и более тяжёлый:
1. Приводим наш тест метод к следующему виду
[Test] [Row("firefox")] [Row("googlechrome")] public void TheGoogleTest(string browser) { Browser = browser; selenium.Open("/"); selenium.Type("q", "Selenium документация"); selenium.Click("btnG"); selenium.WaitForPageToLoad("1000"); Assert.IsTrue(selenium.IsTextPresent("Selenium")); }Минус в том, что метод SeleniumBase.SetupTest() вызывается перед TheGoogleTest, поэтому сначала подыматься дефолтно прописанный браузер в нашем случае это FF.
2. Модифицировать SeleniumBase:
Вынести логику с SetupTest в другой метод к примеру
public void RunServer(string browser) { seleniumServer.Setup(); selenium = new DefaultSelenium("localhost", seleniumServer.ServerPort, "*" + browser,sitePath); selenium.Start(); VerificationErrors = new StringBuilder(); } [SetUp] public void SetupTest() { }И с каждого теста вызывать его
[Test] [Row("firefox")] [Row("googlechrome")] public void TheGoogleTest(string browser) { RunServer(browser); }Плюс в том, что теперь будет вызываться конкретно прописанный браузер, а большим минусом есть то что нужно не забывать в каждом тесте прописывать вызов метода RunServer(browser);
Немного сумбурно, но надеюсь, кому-то упростит роботу.
Полезные ссылки:
http://igorbrejc.net/category/development/testing/gallio-and-mbunit
http://lawrencesong.net/2008/01/selenium-element-locators
http://seleniumhq.org/docs/05_selenium_rc.html
А что SetUpAttribute и RowAttribute не дружат?
ВідповістиВидалитиПо-моему, хорошо описано: в деталях, с примерами, с картинками - все то, чего ждет запутавшийся девелопер.