Upload
igor-bronovskyy
View
378
Download
3
Embed Size (px)
DESCRIPTION
07 - Висновки з TDD, погляд початківця - Віталій Зінченко - IT Event 2013 (5) Буде розглянуто підхід розробки програмного забезпечення та тестів, який дозволить досягти наступних цілей: - глибокий та детальний аналіз вимог; - одне розуміння функціональності продукту для усіх членів команди; - хороша взаємодія між командами розробників та тестувальників; - високий рівень покриття продукту тестами; - скорочення часу необхідного для тестування; Результатом виконання перелічених пунктів стане налагоджений процес розробки продукту, порозуміння між учасниками команди і найголовніше - якісне ПЗ. Віталій Зінченко http://itevent.if.ua/lecture/visnovki-z-tdd-poglyad-pochatkivtsya
Citation preview
Висновки з TDD погляд початківця
Трішки лірики про процес
Приклад реалізації тесту
Віталій Зінченко
Чому виникло бажання про це розповісти?
Подяки:
• http://xpinjection.com
• Микола Аліменков
• Володимир Цукур
• Einar Ingebrigtsen
• Jasson Huggins
• Simon Steward
Робочий процес розробника
аналіз вимог
виділення неподільних елементів
визначення вхідних параметрів і результату
розробка функціоналу
перевірка
створення тестової версії
виправлення помилок
Робочий процес тестувальника
аналіз вимог
виділення неподільних елементів
визначення вхідних параметрів і результату
розробка тестових сценаріїв
перевірка тестової версії
звітування про помилки
Що тут не так?
Давайте вирішувати проблеми, ще до їх появи
ізольований аналіз вимог та їх уточнення
питання - як воно працює?
питання - як воно перевіряється?
Результат:
багато дрібних помилок
уточнення після реалізації
витрачений час
Єдина задача - єдина команда
Реалізація пліч-о-пліч:
аналіз і уточнення вимог
виділення функціональних частин
створення макету продукту
реалізація функціоналу
написання і розробка тестів
збереження робочих даних в одному місці
І ми маємо отаке:
Перевірки при такому підході
менше запитань і узгоджень після реалізації
менше помилок-багів
розробник використовує тести в процесі написання
функціоналу
тестувальник займається створенням тестів, а не їх
проходженням
частіші та однакові регресивні перевірки
Як це все виглядає:
Unit Test, Visual Studio 2012 + NuGet
WebDriver + Selenium
Клас BaseObject
using OpenQA.Selenium; using Selenium; Using OpenQA.Selenium.Support.PageObjects; Using OpenQA.Selenium.Support.UI; namespace FaceBookTest { public class BaseObject { public static IWebDriver Driver; public static DefaultSelenium Selenium; public static void InitPage<T>(T pageClass) where T : BaseObject { PageFactory.InitElements(Driver, pageClass); } } }
Клас BaseTest
using Nunit.Framework; using OpenQA.Selenium.Firefox; using OpenQA.Selenium.IE; using OpenQA.Selenium.Chrome; using Selenium; namespace FaceBookTest { public class BaseTest : BaseObject { [TestFixtureSetUp] public void beforeClass(){ Driver = new FirefoxDriver(); //for IE Driver = new InternetExplorerDriver(@"<DOWNLOAD AND SPECIGY PATH //TO IEDERIVERSERVER HERE(//code.google.com/p/selenium)>"); Selenium = new WebDriverBackedSelenium(Driver, TestTools.homePage); Selenium.Start() } [SetUp] public void beforeTest(){ Driver.Navigate().GoToUrl(TestTools.homePage); } [TestFixtureTearDown] public void afterClass(){ Driver.Close(); Selenium.Close(); } } }
Клас TestTools
using NUnit.Framework; namespace FaceBookTest { class TestTools : BaseObject { public static string homePage = "http://www.facebook.com"; private const int DEFAULT_TIMEOUT = 60; public static void WaitingForElement(string locator, int timeOut = DEFAULT_TIMEOUT) { for (int i = 0; i < timeOut; i++){ if (Selenium.IsElementPresent(locator)){ return; } else{ System.Threading.Thread.Sleep(1000); } } Assert.Fail("Element with '" + locator + "' not found"); } } }
Елементи на Login-сторінці
public class LoginPage : BaseObject public const string USER_NAME_FIELD = "//input[@id='email']"; public const string PASSWORD_FIELD = "//input[@id='pass']"; public const string LOGIN_BUTTON = "//label[@id='loginbutton']/input"; public const string FAILED_LOGIN_TEXT = "//div/p[contains(text(),'The password you entered is incorrect')]"; [FindsBy(How = How.XPath,Using = USER_NAME_FIELD)] public IWebElement userNameField; [FindsBy(How = How.XPath, Using = PASSWORD_FIELD)] public IWebElement passwordField; [FindsBy(How = How.XPath, Using = LOGIN_BUTTON)] public IWebElement loginButton;
Події на Login-сторінці
public static LoginPage GetLoginPage() { LoginPage loginPage = new LoginPage(); InitPage(loginPage); return loginPage; } public LoginPage EnterUserName(string userName){ userNameField.SendKeys(userName); return GetLoginPage(); } public LoginPage EnterPassword(string password){ passwordField.SendKeys(password); return GetLoginPage(); } public UserHomePage ClickLoginButton() { loginButton.Click(); return UserHomePage.GetUserHomePage(); } public LoginPage IsLoginFailed(){ TestTools.WaitingForElement(FAILED_LOGIN_TEXT); return GetLoginPage();}
Тестові методи для Login-сторінки
namespace FaceBookTest { class LoginPageTools { private LoginPage loginPage = new LoginPage(); private UserHomePage userHomePage = new UserHomePage(); public LoginPageTools AssertUserName(string userName){ UserHomePage.AssertUserName(userName); return this; } } public LoginPageTools AssertLoginFailed(){ loginPage.IsLoginFailed(); return this;} public LoginPageTools PleaseLogin(string userName, string password){ BaseObject.InitPage(loginPage); loginPage. EnterUserName(userName). EnterPassword(password). ClickLoginButton(); return this; } } }
Елементи та події на HomePage
public const string DISPLAYED_USER_NAME = "//img[contains(@id,'profile_pic_header')]/../span[contains(text(),'#')]"; public const string USER_NAVIGATION_MENU = "//*[@id='userNavigationLabel']"; public const string LOGOUT_BUTTON = "//input[@value='Log Out']"; [FindsBy(How = How.XPath, Using = USER_NAVIGATION_MENU)] public IWebElement userNavigationMenu; [FindsBy(How = How.XPath, Using = LOGOUT_BUTTON)] public IWebElement logoutButton; public static UserHomePage GetUserHomePage(){ UserHomePage userHomePage = new UserHomePage(); InitPage(userHomePage); return userHomePage; } public UserHomePage AssertUserName(string testUserName){ TestTools.WaitingForElement(DISPLAYED_USER_NAME.Replace("#", testUserName)); return GetUserHomePage(); }
Тестові методи для HomePage
namespace FaceBookTest { class UserHomePageTools { private UserHomePage userHomePage = new UserHomePage(); public UserHomePageTools PleaseLogOut() { BaseObject.InitPage(userHomePage); userHomePage.userNavigationMenu.Click(); userHomePage.logoutButton.Click(); return this; } } }
Тест
namespace FaceBookTest { public class LoginPageTest : BaseTest { private static LoginPageTools loginPageTools = new LoginPageTools(); private static UserHomePageTools userHomePageTools = new UserHomePageTools(); [Test] public static void UserIsAbbleToLogin(){ loginPageTools. PleaseLogin(“[email protected]”, “fb!password13”). AssertUserName(“FBtest User”); UserHomePageTools.PleaseLogOut(); } [Test] public static void UserIsNotAbbleToLogin(){ PleaseLogin(“[email protected]”, “incorrectPassword”). AssertLoginFailed(); } } }
Результати
SpecFlow Додати в проект:
SpecFlow
SpecFlow.NUnit
Створити SpecFlow Feature File
Код тесту
namespace FaceBookTest { [Binding] public class LoginFeatureSteps : BaseTest { private static LoginPageTools loginPageTools = new LoginPageTools(); private static UserHomePageTools userHomePageTools = new UserHomePageTools(); [AfterScenario()] public void TearDown() { afterClass(); } [Given(@"FaceBook Login Page is opened")] public void GivenFaceBookLoginPageIsOpened() { specFlowInit();} [When(@"Enter credentials (.*)/(.*) and press Login button")] public void WhenEnterCredentialsAndPressLogin(string p0, string p1) { loginPageTools.PleaseLogin(p0, p1); } [Then(@"User Name (.*) is displayed on the Home Page")] public void ThenUserNameIsDisplayedOnTheHomePage(string p0) { loginPageTools.AssertUserName(p0); userHomePageTools.PleaseLogOut(); } } }
Додати в BaseTest.сs public void specFlowInit() {beforeClass(); beforeTest();}
Результати
//