Тестирование ПО. Тестирование. Реферат актуальность. Основной всплеск интереса к теме тестирования пришёлся на 90е годы и начался в сша. Бурное развитие систем автоматизированной разработки
Скачать 2.21 Mb.
|
Что нужно сделать: 1) добавить в Solution новый проект (Class library). Это название позже нужно прописать в App.config; 2) подключить ссылки; В итоге должно быть как на Рисунке 12.1. Рисунок 12.1 - Новый проект 100 3) создать файл конфигурации App.config; В этом файле будут содержаться все основные параметры проекта. Подробнее App.config: WebPages должна быть папка Yandex) --> (кол-во строк) --> 101 4) создать папку для страниц (WebPages); В этой папке будут находиться файлы с классами страниц. Подробнее. WebPages. Несколько правил: папка со страницами должна называться WebPages; она должна находиться в корне проекта; внутри нее должны содержаться корневые папки ваших тестируемых системы (к примеру если тестировать Яндекс, то в папке WebPages должна быть папка yandex); страницы в папках должны находиться в той же иерархии, как они находятся в тестируемой системе. Пример: Страница: test.ru/step1/service/index.html Иерархия папок: WebPages -> Test -> step1 -> service -> index.html.cs Важно: имена папок и классов чувствительны к регистру Названия файлов классов страниц должны соответствовать реальным именам страниц. Названия классов страниц: Пример: Страница: index-1.html Класс: index___1__html Здесь: дефис в названии страницы заменяется тремя слешами (можно изменить, параметр dash_prefix в App.config); точка файла заменяется двумя слешами (можно изменить, параметр extension_prefix в App.config. Названия классов, когда нет названия файла, а есть только папка: Пример: Страница: test.ru/step1/service/ Класс: _fld (можно изменить, параметр folder_index_prefix в App.config) 5) создать класс Pages.cs; public static class Pages { } Класс будет содержать объекты классов страниц (WebPages) Подробнее. Pages.cs 102 Этот класс содержит объекты классов страниц, через которые осуществляется доступ к элементам и т.д. Несколько правил: в данном классе иерархия подклассов должна совпадать с иерархией в папке WebPages; класс и все объекты внутри него должны быть public static. Пример класса: public static class Pages { public static class Test { public static index__html Index = new index__html(); public static class step1 { public static class service { public static _fld Main = new _ fld(); } public static add__php Add = new add__php(); } } } При такой записи страницы будут доступны в тестах примерно так: Pages.Test.Index.Open(); Pages.Test.step1.service.Main.Open(); 6) создать папку для тестов (Tests); Здесь нет особых правил, достаточно создать в корне проекта папку Tests, внутри нее создать папки с тестами по тестируемым системам. Подробнее. Tests На рисунке 12.2 изображено как это сделано в проекте: Рисунок 12.2 - Иерархия Tests Рекомендуется создать два «служебных» теста, которые всегда будут запускаться первым и последним. В первом тесте можно выполнять различные действия по настройке среды, в 103 последнем, к примеру, выполнять очистку стенда и запускать нотификацию. Nunit запускает тесты внутри категории в алфавитном порядке (по полному названию классов). Для запуска нотификации необходимо выполнить код: AT.Service.Notifier.SendNotif(); Пример создания страницы (WebPages) Все создаваемые страницы наследуются от базового класса PageBase, который содержит необходимые методы, одинаковые для всех страниц: «открыть», «открыть с параметром», «получить Url». Пример класса страницы: public class index__php : PageBase { public void OpenVpdnTab() { new WebElement().ByXPath("//a[contains(@href, '#internet')]").Click(); } public string VpdnAction { get { return new WebElementSelect().ByXPath("//select[@name='action']").GetSelectedValue(); } set { new WebElementSelect().ByXPath("//select[@name='action']").SelectByValue(value); } } public string VpdnLid { set { new WebElement().ByXPath("//input[@name='lid']").SendKeys(value); } } public string VpdnTechlist { set { new WebElement().ByXPath("//input[@name='file']").SendKeys(value); } } public string VpdnStartDate { set { new WebElement().ByXPath("//input[@name='start_date']").SendKeys(value); } } public void VpdnSubmit() { new WebElement().ByXPath("//input[@value='Применить']").Click(); } } Правило: Все элементы, которые присутствуют на странице, должны инициализироваться в момент обращения к ним. Примеры работы со страницами: Pages.Test.Index.Open(); — открыть Pages.Test.Index.Open(“?id=1”); — открыть с параметром var url = Pages.Test.Index.Url; — получение адреса страницы Pages.Test.Index.VpdnSubmit(); — запуск функции, прописанной в классе страницы выше 104 Пример создания тест-кейса (Test) Как уже отмечалось выше, все тест-кейсы должны лежать в папке Tests. Все тест-кейсы должны быть public и наследоваться от базового класса TestBase. Перед названием класса с тест-кейсом должен быть указан атрибут [TestFixture]. Перед каждым шагом тест-кейса должен быть указан атрибут [Test]. Подробнее об атрибутах тестов можно почитать в документации NUnit. Пример класса с тест-кейсом: namespace TestProject.Tests.OSE { [TestFixture] [Category("OSE"), Category("OSE_Internet")] /* категории, nunit позволяет запускать тесты выборочно по категориям */ public class test_253750 : TestBase { [Test] public void step_01() { Pages.OSE.Inaclogin.Open(); Pages.OSE.Inaclogin.Login = “user”; Pages.OSE.Inaclogin.Password = “password”; Pages.OSE.Inaclogin.Submit(); Assertion("Ошибка авторизации”, () => Assert.AreEqual(Pages.OSE.Inaclogin.IsAuthSuccess, true)); } } } Assertion – это проверка выполнения условия. Формат записи: Assertion (текст ошибки, () => Assert.любой_accert_из_nunit() ); Почему не используем просто Assert? Все Assert’ы отлавливаются специальным классом, в котором выполняются действия по регистрации ошибок, логирования и т.д. Примеры работы с БД Для работы с БД используется класс AT.DataBase.Executor, содержащий методы: выполнение запросов на выборку (select); выполнение запросов типа insert, update, delete (unselect); выполнение хранимых процедур. 105 Примеры: Select: var query = select col1, col2 from table_name"; var list = Executor.ExecuteSelect(query, Environment.Имя_БД); Unselect: var query = “DELETE FROM table_name"; Executor.ExecuteUnSelect(query, Environment.Имя_БД); Выполнение хранимой процедуры: Executor.ProcedureParamList.Add(new ProcedureParam("varchar", "имя_параметра", «значение»)); /* входной параметр */ Executor.ProcedureParamList.Add(new ProcedureParam("varchar")); /* возвращаемое значение */ var res = Executor.ExecuteProcedure("имя_процедуры", Environment.Имя_БД); имя_БД должно соответствовать значению sid из строки инициализации БД в App.config Сбор результатов тестирования и пример отчета: Как уже упоминалось выше, для запуска нотификации и получения отчета на почту необходимо после запуска последнего теста выполнить код AT.Service.Notifier.SendNotif(). Логика NUnit такова, что он запускает тесты в алфавитном порядке, соответственно чтобы нужный тест запустился последним, его нужно назвать соответствующим образом. Настройки оповещения указываются в файле App.config. На рисунке 12.3 изображен пример отчета. Рисунок 12.3 - Пример отчета Выполнив все пункты этой инструкции юный тестировщик — автоматизатор сможет в короткие сроки создать свой проект и получить тот минимум, который необходим для начала этого пути. 106 12.8 Проект авто-тестов для веб-сервиса Эксперт В заключении будет рассмотрен завершенный проект по автоматизированному тестированию для веб-сервиса Эксперт. «Эксперт» - это веб-сервис для оценки финансового состояния предприятия и оценки вероятности налоговой проверки. Цель создания проекта: ускорить регрессионное тестирование и выпуск обновлений. Ускорить время прохождения всех тестов. Изначально автоматизированные тесты были написаны на языке C#, но ввиду их медленного прохождения (из-за большого их количества, специфики самого веб-сервиса и то, что работать с ними можно было только под Windows) было принято решение переписать все тесты на языке Scala. Среда разработки - Eclipse. Технический драйвер, который связывает тесты и бразуер - Selenium Web Driver. WebDriver – не инструмент автоматизации тестирования, а лишь средство управления браузером. В качестве примера, для написания тестов, будет рассмотрена одна страница Эксперта, изображенная на рисунке 12.4: написание для нее инфраструктуры и тест кейсов. Настройки площадок и различных конфигурационных файлов, а также сам запуск тестов будут опущены. Рисунок 12.4 - Данные об организации 12.8.1 Описание инфраструктуры страницы Перед тем как начать писать тест-кейсы для страницы, ее нужно описать, т.е. создать инфраструктуру. Инфраструктура представляет собой описание тестируемых элементов рассматриваемой страницы. В данном случае это поля: названия организации, ОПФ, ОВД и денежный единицы; кнопки "назад" и "далее"; а также различные валидационные сообщения. 107 Чтобы описать инфраструктуру элементов страницы, нужно знать как обратиться к этому элементу. Для это может помочь консоль разработчика в браузере, изображенная на рисунке 12.5. Создание нового элемента является одновременно проверкой того, что этот элемент есть на странице и он видим. Если элементы появляются после определённых действий или не все элементы могут одновременно присутствовать на странице, нужно использовать ленивость с помощью модификатора lazy. В таком случае, первое обращение к элементу будет одновременно проверкой его существования на странице. Рисунок 12.5 - Консоль разработчика Узнав как обращаться к элементу, можно представить это в коде: val companyTitle = new ExpertInput(ByJQ("input#company_title")) Т.к. в поле "название организации" происходит ввод данных, то используется элемент ExpertInput и запрос JQ, чтобы можно было определить данное поле на страницы. По тому же принципу описывается элемент ОПФ. val orgType: ExpertSelect[OrgTypes.type] = new ExpertSelect(ByJQ("select#org_type") ОПФ является списком, который изображен на рисунке 12.6, поэтому используется уже не ExpertInput, а ExpertSelect. При этом нужно описать все элементы этого списка, для этого используется объект OrgTypes: object OrgTypes extends StringEnumeration { val empty = StringValue("…") val OOO = StringValue("Общество с ограниченной ответственностью") val OAO = StringValue("Открытое акционерное общество") val ZAO = StringValue("Закрытое акционерное общество") val UP = StringValue("Унитарное предприятие") val ODO = StringValue("Общество с дополнительной ответственностью") val PT = StringValue("Полное товарищество") val TV = StringValue("Товарищество на вере") val PK = StringValue("Производственный кооператив") val KKH = StringValue("Крестьянское (фермерское) хозяйство") val NKO = StringValue("Некоммерческая организация") val IP = StringValue("Индивидуальный предприниматель") val OBPUL = StringValue("Организация без прав юридического лица") } 108 Рисунок 12.6 - Список ОПФ Денежные единицы тоже являются списком, но т.к. он состоит всего из двух элементов, то принято решение описать выбор между элементами как 2 функции. def chooseThousandsUnit : FaCompanyInfoPage[Intro, Result] = { unitOfMeasure.select(UnitsOfMeasure.thousands) new FaCompanyInfoPage(url) } def chooseMillionsUnit : FaCompanyInfoPage[Intro, Result] = { unitOfMeasure.select(UnitsOfMeasure.millions) new FaCompanyInfoPage(url) } На странице также есть и скрытые элементы, показанные на рисунке 12.7, которые появятся на ней только при определенных условиях. В данном случае - это валидационные сообщения. Их тоже необходимо описать, т.к. все тест кейсы будут нацелены на проверку валидации. Рисунок 12.7 - Скрытые элементы Код для текста валидации: val companyNameValidation = "Укажите название" val orgTypeValidation = "Заполните поле" val onvdCodeValidation = "Укажите основной вид деятельности" lazy val moneyUnitValidation = "Переключение единиц измерения невозможно — значения должны быть целыми числами" Функции проверки валидации: def checkCompanyNameValidation() = checkText(ByJQ("label[for='company_title']"), companyNameValidation) def checkOrgTypeValidation() = checkText(ByJQ("label[for='org_type']"), orgTypeValidation) def checkOnvdCodeValidation() = checkText(ByJQ("label[for='onvd_code']"), onvdCodeValidation) def checkMoneyValidation() { moneyUnitElement.text should be(moneyUnitValidation) } 109 Полное описание страницы можно увидеть в приложении А. 12.8.2 Написание тест кейсов Рассмотрим простой сценарий: после того как пользователь попадает на страницу "Данные об организации" он нажимает кнопку "Далее" не заполнив ни одного поля. Ожидаемый результат: сработает валидация на все поля. После этого он заполнит одно поле - валидация со всех полей исчезает. Код в этом случае выглядит следующим образом: Т.к. для каждого теста нужно находится на страницу "Данные об организации", то нужно повторяющийся код вывести в функцию. В данном случае это шаги выбора финансового анализа, периода и возможность заполнения полей вручную. protected def setup = { IntroPage().new_fa.proceed().chooseManual.selectPeriod(Years.year2013, PeriodTypes.year) После идет описание шагов в код: "Click next with empty fields than fill onvd code ‐ all fields" should "be valid" in { val companyInfoPage = setup companyInfoPage.nextPageInactive.click() companyInfoPage.checkCompanyNameValidation() companyInfoPage.checkOnvdCodeValidation() companyInfoPage.checkOrgTypeValidation() companyInfoPage.onvdCodeSelectorLink.proceed().checkOnvd("15") withWait() {new ExpertText(ByJQ("label[for='company_title']"))} withWait() {new ExpertText(ByJQ("label[for='org_type']"))} withWait() {new ExpertText(ByJQ("label[for='onvd_code']"))} } Шаги: срабатывает повторяющийся код - открывается страница "Данные об организации"; нажатие на кнопку "Далее"; проверка, что появилась валидация для полей названия организации, ОПФ, ОВД; выбирается из списка ОВД значение; проверяется, что валидация со всех трех полей исчезает. Рассмотрим еще один сценарий: пользователь заполняет все поля на странице "Данные об организации", нажимает кнопку "Далее" и переходит на следующую страницу. После этого он нажимает на кнопку "Назад" и попадает на предыдущую страницу, при этом все поля должны быть заполнены старыми значениями. Код: "Fill all fields, click next than return back ‐ all fields" should "be filled" in { val companyInfoPage = setup companyInfoPage.companyTitle.text = OrgName.name companyInfoPage.orgType.select(OrgTypes.ODO) 110 companyInfoPage.onvdCodeSelectorLink.proceed().checkOnvd("15").nextPage.proceed().backwardLin k.proceed() companyInfoPage.companyTitle.text should be(OrgName.name) companyInfoPage.orgType.getSelected should be(OrgTypes.ODO.toString()) companyInfoPage.onvd.text should be("15. Производство пищевых продуктов, включая напитки") } |