Roman Iovlev - Test UI with JDI - Selenium Camp.pptx
- Количество слайдов: 104
UI WITH JDI EASY FAST GOOD 24 FEBRUARY 2017
ROMAN IOVLEV Chief QA Automation In Testing more than 11 years In Testing Automation 9 years
? 3
JDI SETUP https: //github. com/epam/JDI http: //jdi. epam. com/ https: //vk. com/jdi_framework README 4
JDI SETUP Maven, Gradle, Ivy <dependency> <group. Id>com. epam. jdi</group. Id> <artifact. Id>jdi-uitest-web</artifact. Id> <version>1. 0. 58</version> </dependency> https: //github. com/epam/JDI-Examples https: //github. com/epam/JDI README 5
FAQ 6
SIMPLE TEST Product. Page. Product. Type. Select( «jacket» ); Product. Page. Price. select( « 500$» ); Product. Page. Colors. check( «black» , «white» ); Assert. is. True(Product. Page. Label. get. Text(), «Armani Jacket» ) 7
SIMPLE TEST Login. Page. Open(); Login. Page. Login. Form. Login(admin); Search. Page. Search. Find( «Cup» ); Assert. Are. Equal(Results. Page. Products. Count(), expected); 8
PAGE ELEMENTS 9
PAGE OBJECTS Tests Driver (Engine) Page Objects Application ELEMENTS private Web. Element User. Name; private Web. Element Password; private Web. Element Login. Button; • ACTIONS • BUSINESS ACTIONS • Enter. User. Name(String name); • Login(User user) • Enter. Password(String name); • Click. Login. Button(); 10
PAGE ELEMENTS ELEMENT public Text. Field User. Name; public Text. Field Password; public Button Login. Button; public Drop. Down User. Status; • ACTIONS • --- • BUSINESS ACTIONS • ACTIONS • • Select(string option) bool Is. Selcted() List<string> All. Options() string Get. Value() • Login(User user) 11
ELEMENTS v Simple v Complex v Composite 12
SIMPLE ELEMENTS 13
SIMPLE ELEMENTS @Find. By (css=“. description”) public Text description; public Button submit; public Label product. Name; public Link follow. Me; public Text. Field password; public Text. Area abuse; public Check. Box remember. Me; public Date. Picker date; public File. Input upload; public Image photo; NEWS 14
SIMPLE ELEMENTS @Find. By (css=“. btn”) public Button submit; @Find. By (css=“. btn”) public Button submit = new Button(By. css(“. btn”)); @Find. By (css=“. btn”) public IButton submit; @Find. By (css=“. btn”) @Find. By (xpath=“//button”) @Find. By (id=“button-id”) @Find. By (name=“button”) @JFind. By (text=“Submit”) @JFind. By (model=“btn-model”) @JFind. By (binding=“btn”) @JFind. By (repeater=“r-button”) 15
MULTILOCATORS Multi language testing Multi version testing @JFind. By (text=“Submit”, group=“ 1. 7”) @JFind. By (text=“Submit”, group=“en”) @JFind. By (text=“Отправить” , group=“ru”) @JFind. By (value=“Submit” , group=“ 2. 0”) public Button submit; 16
PLATO'S THEORY OF FORMS IButton No application but you can write UI Objects (Page Objects ) 5
COMPLEX ELEMENTS 18
COMPLEX ELEMENTS public Dropdown colors; public Checklist settings; public Combo. Box tags; public Drop. List shirt. Sizes; public List<Element> search. Results; public Elements reviews; public Table products; public Menu main. Menu; public Tabs areas; public Selector vote; public Radio. Buttons rating; public Text. List chat; 19
COMPLEX ELEMENTS @JDropdown ( root = @Find. By(css = “. colors"), value = @Find. By(css = “. value"), element. By. Name = @Find. By(tag. Name = “li")) public Dropdown colors; @JTable( root = @Find. By (css = “. offers"), row = @Find. By (xpath = ". //li[%s]//div"), column = @Find. By (xpath = ". //li//div[%s]"), header = {“ID", “Title", “Apply”} ) public Table offers; 20
COMPLEX ELEMENTS @Find. By(css = “. colors") public Dropdown colors; @Find. By(css = “. table”) public Table offers; @Find. By(css = “. menu li”) public Menu navigation; @Find. By(css = “. menu ul”) public Menu navigation; @Find. By(xpath = “//*[@class=‘menu’]//li[text()=‘%s’]”) public Menu navigation; 21
USING ENUMS 22
ENUMS IN COMPLEX ELEMENTS public Menu<Options> top. Menu; public enum Options { Home, About, Contacts } top. Menu. select(About); top. Menu. select(Options. About); public Dropdown<Colors> colors; public Tabs<Areas> areas; public Checklist<Settings> settings; public Combo. Box<Tags> tags; public Drop. List<Sizes> shirt. Sizes; public Selector<Vote. Options> vote; public Radio. Buttons<Ratings> rating; public enum Options { Home(‘option-1’), About(‘option-3’), } public String value; Options (String value) { this. value = value; } @Override public String to. String() { return value; } 23
TYPIFIED ELEMENTS • Code readability • Clear behavior • Union of all element’s locators • Union of element and its actions • Detailed logging 24
COMPARE Text Description; Button Submit; Label Product. Name; Link Follow. Me; Text. Field Password; Text. Area Abuse; Check. Box Remember. Me; Date. Picker Date; File. Input Upload; Image Photo; Web. Element Description; Web. Element Submit. Button; Web. Element Product. Name; Web. Element Follow. Me. Link; Web. Element Password. Field; Web. Element Abuse; Web. Element Remember. Me; Web. Element Date. Picker; Web. Element Upload; Web. Element Photo; 25
COMPARE @JDropdown (root = @Find. By(css = “. colors"), value = @Find. By(css = “. value"), element. By. Name = @Find. By(tag. Name = “li")) Dropdown Colors; @Find. By(css = “. colors. value") Web. Element Colors. Value; @Find. By(css = “. colors li") List<Web. Element> Colors. List; public string get. Color() { return Colors. Value. get. Text(); } public void select. Color(string color. Name) { Colors. Value. Click(); for (Web. Element color : Colors. List) if (color. get. Text(). Equals(color. Name) { color. Click(); return; 26 }
COMPARE @Find. By (id = “trades") public Table Colors; @Find. By(css = "") private List<Web. Element> results. Col. Headers; @Find. By(css = "") private List<Web. Element> results. Rows. Headers; @Find. By(css = "") private List<Web. Element> results. Cells. Headers; @Find. By(css = "") private List<Web. Element> results. Column; @Find. By(css = "") private List<Web. Element> results. Row; column) { } ITable use. Cache(boolean value) { } ICell cell(Column column, Row row) { } Map. Array<String, ICell> row(String value, ICell cell(String column. Name, String ITable use. Cache() { } Column column) { } row. Name) { } Table clone() { } Map. Array<String, ICell> column(String value, Table copy() { } ICell cell(int column. Index, int row. Index) { } Row row) { } List<ICell> cells(String value) { } ITable has. All. Headers() { } Map. Array<String, ICell> row(int row. Num) { } ITable has. No. Headers() { } List<ICell> cells. Match(String regex) { } Map. Array<String, ICell> row(String row. Name) ITable has. Only. Column. Headers() { } ICell cell(String value) { } {} ICell cell. Match(String regex) { } ITable has. Only. Row. Headers() { } Map. Array<String, ICell>> List<String> row. Value(int col. Num) { } ITable has. Column. Headers(List<String> value) { List<String> row. Value(String col. Name) { } rows(String. . . col. Name. Values) { } } Map. Array<String, ICell>> Map. Array<String, ICell> column(int col. Num) { <THeaders extends Enum> ITable } columns(String. . . row. Name. Values) { } has. Column. Headers(Class<THeaders> headers) boolean wait. Value(String value, Row row) { } Map. Array<String, ICell> column(String {} boolean wait. Value(String value, Column col. Name) { } ITable has. Row. Headers(List<String> value) { } column) { } List<String> column. Value(int col. Num) { } <THeaders extends Enum> ITable boolean is. Empty() { } List<String> column. Value(String col. Name) { } has. Row. Headers(Class<THeaders> headers) { } boolean wait. Have. Rows() { } Map. Array<String, Select. Element> header() { } ITable set. Columns. Count(int value) { } boolean wait. Rows(int count) { } Select. Element header(String name) { } ITable set. Rows. Count(int value) { } ICell cell(String value, Row row) { } List<String> headers() { } ICell cell(String value, Column column) { } List<String> footer() { } List<ICell> cells. Match(String regex, Row row) { List<ICell> get. Cells() { } } void clean() { } List<ICell> cells. Match(String regex, Column void clear() { } 27
COMPOSITE ELEMENTS 28
COMPOSITE ELEMENTS public class Header extends Section @JPage(url = "/index. html", title = “Good site") public class Home. Page extends Web. Page @JSite(domain = “http: //epam. com/") public class Epam. Site extends Web. Site public class Login. Form extends Form public class Search. Bar extends Search public class Alert extends Popup public class Navigation extends Pagination 29
TEST PROPERTIES driver=chrome timeout. wait. element=10 domain=https: //www. epam. com/ driver. get. Latest=true $ mvn install -Dbrowser=firefox -Ddomain=http: //… driver=${browser} domain=${domain} … 30
WEB SITE @JSite(domain = “http: //epam. com/") public class Epam. Site extends Web. Site { @JPage(url = "/index. html") public static Home. Page homepage; @JPage(url = "/login", title = “Login page") public static Login. Page login. Page; @Find. By (css=“. nav”) public static Menu navigation; } @Before. Suite(always. Run = true) public static void set. Up() { Web. Site. init(Epam. Site. class); } 31
WEB PAGE @JPage(url = "/main", title = "Good site", url. Template = “/main? d{10}“, url. Check. Type = MATCH, title. Check. Type = CONTAINS) public class Home. Page extends Web. Page USAGE homepage. open(); homepage. check. Opened(); homepage. is. Opened(); homepage. refresh(); homepage. back(); homepage. forward(); homepage. add. Cookie(); homepage. clear. Cache(); 32
SECTION public class Header extends Section { @Find. By (css=“. submit”) public Button submit; @Find. By (css=“. follow. Me”) public Link follow. Me; @Find. By (css=“. navigation”) public Menu navigation; } USAGE header. submit. Click(); header. menu. is. Selected(); header. open. About(); public void open. About() { follow. Me. Click(); navigation. select(ABOUT); } 33
ENTITY DRIVEN TESTING 34
EDT: DATA DRIVEN TESTING Ø Provide List<User> for test 35
EDT: PRECONDITIONS Ø Provide List<User> for test 0. Have Default. User in DB ? + 36
EDT: FILL AND SUBMIT Ø Provide List<User> for test 0. Have Default. User in DB 1. Login with Default. User 37
EDT: FILL AND SEND Ø Provide List<User> for test 0. Have Default. User in DB 1. Login with Default. User 2. Submit Contact Us Form for Default. User 38
EDT: EXTRACT Ø Provide List<User> for test 0. Have Default. User in DB 1. Login with Default. User 2. Submit Contact Us Form for Default. User 3. Get Act. Opening from Vacancy table 39
EDT: VALIDATE Ø Provide List<User> for test 0. Have Default. User in DB 1. Login with Default. User 2. Submit Contact Us Form for Default. User 3. Get Act. Opening from Vacancy table 4. Assert Act. Opening equals to Exp. Opening Actual Expected 40
FORM public class Login. Form extends Form<User> { @Find. By (css=“. login”) public Text. Field login; @Find. By (css=“. psw”) public Text. Field password; @Find. By (css=“. submit”) public Button submit; @Find. By (css=“. cancel”) public Button cancel; } public class User { public String login = “roman”; } public String password = null; @Test public class simple. Test(User user) { login. Form. login(user); … } 41
ENTITY DRIVEN TESTING @Test public void form. Test(User admin) { login. Form. login. As(admin); filter. select(admin. name); Assert. each(results). contains(admin. name); results. get(1); pay. Form. submit(admin. credit. Card); Assert. are. Equals(DB. Transactions. get(1), admin. credit. Card); } USAGE login. Form. fill(user); login. Form. submit(user); login. Form. verify(user); login. Form. check(user); login. Form. cancel(user); login. Form. save(user); login. Form. publish(user); login. Form. search(user); login. Form. update(user); … 42
• @JTable( • root = @Find. By(class. Name = "search-result-list"), • row = @Find. By(xpath = ". //li[%s]//div"), • column = @Find. By(xpath = ". //li//div[%s]"), • header = {"name", "category", "location", "apply"}) • public Entity. Table<Job, Job. Record> jobs = • new Entity. Table<>(Job. class, Job. Record. class); 43
ENTITY TABLES Jobs. Row job = jobs. Page. jobs. first. Row(r -> text. Of(r. title). equals(“Senior QA Engineer”) && text. Of(r. location). equals(“Saint-Petersburg”)) job. apply. agree. click(); List<Job> jobs = jobs. Page. jobs. entites(); Assert. entities. Are. Equals(jobs, expected. Jobs); 44
ELEMENTS @Find. By(css = ". list. ui-sortable") public Elements<Film. Card> film. Cards; film. Cards. get(name). title. get. Text(); Assert. list. Equals(film. Cards. as. Data(Film. class), films); 45
OTHER UI OBJECTS public class Search. Bar extends Search { } public class Navigation extends Pagination { } public class Confirmation extends Popup { } … public class My. Custom extends Custom. Object { } // implements IComposite 46
UI OBJECTS PATTERN 47
UI OBJECTS Popular test pattern Page Objects 48
UI OBJECTS Useful test approach UI Elements 49
UI OBJECTS Flexible implementation Interfaces 50
UI OBJECTS Page Objects UI Elements UI OBJECTS Interfaces 51
TEST SETTINGS 52
TEST PROPERTIES driver=chrome timeout. wait. element=10 domain=https: //www. epam. com/ driver. get. Latest=true search. element. strategy=strict | soft browser. size=1800 X 1000 demo. mode=false | true log. message. format = short run. type=local | remote cache=false screenshot. strategy=on fail | on | off mvn cmd parametres driver=${browser} domain=${domain} … 53
SETTINGS DRIVER DEMO driver=chrome | firefox | ie driversion=2. 23 driver. get. Latest=true browser. size=1800 X 1000 | max | full driver. path=C: \Selenium demo. mode=false | true demo. delay=2 elements screenshot. strategy= on fail | on | off timeout. wait. element=10 log. message. format=short | full cache=false | true SCREENSHOTS 54
SETTINGS SEARCH ELEMENT search. element. strategy=strict | soft | visible, multiple | any, single visible - accept only visible elements; any - accepts any elements found single - if found more than 1 element > throw error multiple - if found more than 1 element > takes first element strict = visible, single soft = any, multiple 55
LOGGER 56
LOG 4 G Log 4 J log 4 j. root. Logger = info, console log 4 j. appender. console = org. apache. log 4 j. Console. Appender log 4 j. appender. console. layout = org. apache. log 4 j. Pattern. Layout log 4 j. appender. console. layout. Conversion. Pattern = %m%n log 4 j. root. Logger = debug|error, file, HTML, dailylog 4 j. appender. file=org. apache. log 4 j. Rolling. File. Appender log 4 j. appender. file. File=target/. logs/events. log 4 j. appender. file. layout. Conversion. Pattern= %d{yyyy-MM-dd HH: mm: ss} %-5 p %c{1}: %L - %m%n log 4 j. appender. file. layout=org. apache. log 4 j. Pattern. Layout 57
LOGGING JDISettings. logger = Super. Logger(); logger. info(“Start tests”); colors. select(BLUE); [Info] 10: 20. 154 Start tests [Info] 10: 20. 220 Select Blue for Selector ‘Colors' (. Selector; css=‘. colors') [Debug] 10: 21. 004 Get web element for Clickable 'Clickable' (. Clickable; css=‘. colors’) [Debug] 10: 21. 932 Done 58
LOG IN BDD STYLE Product. Page. Product. Type. select( «jacket» ); Product. Page. Price. select( « 500$» ); Product. Page. Colors. check( «black» , «white» ); I select ‘jacket’ Product. Type on Product. Page I select ‘ 500$’ Price on Product. Page I check ‘black’ and ‘white’ Colors on Product. Page 59
STRUCTURE 60
STRUCTURE • test. properties • log properties • ui objects • test init • tests 61
CUSTOMIZATION 62
CUSTOM ACTIONS public Dropdown<Types> product. Types = new Dropdown<Types>() { @Override public void select. Action(String name) { }; } super. select. Action(name); label. click(); 63
CUSTOM ELEMENTS public class Tree. Dropdown<T extends Enum> extends Dropdown<T> { … @Override protected void select. Action(String name) { expand. Action(); String[] nodes = name. split(" > "); Search. Context context = get. Driver(); if (tree. Locators. size() >= nodes. length) for (int i=0; i < nodes. length; i++) { String value = nodes[i]; context = first(context. find. Elements(tree. Locators. get(i)), el -> el. get. Text(). equals(value)); new Clickable((Web. Element) context). click(); } } } 64
CUSTOM SCENARIOS @Before. Suite (always. Run = true) public static void set. Up() { Action. Scenrios. action. Scenario = (element, action. Name, j. Action, level) -> { logger. info(format("Do '%s' action", action. Name)); j. Action. invoke(); }; Action. Scenrios. result. Scenario = (element, action. Name, j. Action, log. Result, level) -> { } }; logger. debug(format("Do '%s' action", action. Name)); Object result = j. Action. get(); logger. info(format("Get '%s' action result: %s", action. Name, result)); return result; 65
STABLE SEARCH public boolean wait(Boolean. Supplier wait. Case) { while (!timeout. Passed()) try { if (wait. Case. get. As. Boolean()) return true; sleep(retry. Timeout. In. MSec); } catch (Exception ex) {throw new Exception(ex); } … } 66
ELEMENT SEARCH @Before. Suite (always. Run = true) public static void set. Up() { Selenium. Driver. Factory. element. Search. Criteria = el -> el. is. Enabled() && el. is. Displayed(); // el -> el != null; }; @Test() public void simple. Test() { sum. Result. avatar. local. Element. Search. Criteria = el -> !el. get. Attribute(“display”). equals(“none”); }; 67
PRECONDITIONS 68
NO TEST DEPENDENCIES @Test(depends. On. Methods = “login. Test”) public void simple. Test() { … }; @Test(depends. On. Groups = “smoke”) public void simple. Test() { … }; 69
PRECONDITIONS 1. Independent tests 2. Time optimization JDI Page precondition PRECONDITION JDI State precondition 1. Is. In. State. Check. Action 2. Move. To. State. Action home. Page. is. Opened(); Preconditions. State. is. In. State(LOGGED_IN) or is. In. State(LOGGED_IN) 70
PRECONDITIONS public enum Preconditions implements IPreconditions { CALC_INIT(() -> calculator. value == 0, () -> { calculator. clear(); calculator. clear. Memeory() }), CAREERS_PAGE("/careers"); …. } 71
DEMO: PRECONDITIONS 72
MATCHERS 73
MODULE STRUCTURE 74
MATCHERS Assert. contains("Test Text", "Text"); Assert. matches("1352 -423 -85746", "\d{4}-\d{3}-\d{5}"); Assert. array. Equals(search. Results, expected. Results); Assert. list. Equals(orders, expected. Orders); Assert. each(search. Results). contains("IPhone"); Assert. each(search. Results). matches("IPhone \d. *"); Assert. are. Equals(() -> get. Next(), "IPhone 6"); Assert. contains(() -> get. Next(), "IPhone 5") Assert. throw. Exception(this: : request, “Bad Request"); Assert. has. No. Exceptions(this: : request); 75
MATCHERS new Check(“Search results are correct”). list. Equals(search. Results, expected. Results); Screen. Assert. matches("1352 -423 -85746", "\d{4}-\d{3}-\d{5}"); Assert. ignore. Case(). are. Equals(result, "IPhone 6"); Assert. wait. Timeout(2). contains(() -> result, "IPhone"); Assert. do. Screenshot(SCREEN_ON_FAIL). is. True(2 * 2 == 4); Assert. fail(“Houston we have a problem”); throw Assert. exception(“Something goes wrong”); 76
INTERFACES 77
TEST ANY UI Selenium <dependency> <group. Id>com. epam. jdi</group. Id> <artifact. Id>jdi-uitest-web</artifact. Id> <version>1. 0. 39</version> </dependency> Your Engine (Driver) Appium <dependency> <group. Id>com. epam. jdi</group. Id> <artifact. Id>jdi-uitest-mobile</artifact. Id> <version>1. 0. 39</version> </dependency> Sikuli / Winnium <dependency> <group. Id>com. epam. jdi</group. Id> <artifact. Id>jdi-uitest-gui</artifact. Id> <version>1. 0. 39</version> </dependency> 78
JDI ARCHITECTURE Commons Matchers Core Web, Mobile, Gui … INTERFACES public interface ICheck. Box extends IClickable, ISet. Value { void check(); void uncheck(); boolean is. Checked(); } IButton ICheck. Box IDate. Picker IFile. Input IImage ILabel ILink IText. Area IElement ISelector IComposite IPage IText. Field ICheck. List ICombo. Box IDrop. Down IDrop. List IForm IGroup IMenu IPage IHas. Value ISet. Value IPagination IPopup IRadio. Buttons ISearch ISelector ITabs IText. List 79
INTERFACES public class Header extends Section { @Find. By (css=“. submit”) public IButton submit; @Find. By (css=“. follow. Me”) public ILink follow. Me; @Find. By (css=“. navigation”) public IMenu navigation; } Map. Interface. To. Element. update( new Object[][] { { IDrop. Down. class, My. Drop. Down. class}, { IButton. class, My. Button. class}, { ITable. class, Custom. Table. class} }); 80
PARALLEL TEST RUN 81
PARALLEL TEST RUN <? xml version="1. 0" encoding="WINDOWS-1251"? > <!DOCTYPE suite SYSTEM "http: //testng. org/testng-1. 0. dtd"> <suite name="Test suite" parallel="methods" thread-count="2"> <test name="Tests" preserve-order="true"> <classes> <class name="com. epam. jdi. uitests. testing. simple. examples. Table. Examples"/> <class name="com. epam. jdi. uitests. testing. career. common. tests. Career. Tests"/> <class name="com. epam. jdi. uitests. testing. simple. examples. Form. Examples"/> </classes> </test> </suite> 82
INSTRUCTION 83
FIRST RUN 1. Download project template from Github https: //github. com/epam/JDI link “Simple Java example project” In Readme 2. Add (replace examples) UI objects for your project in src/main/…/uiobjects 3. Add tests in src/test/…/tests 4. Add Data. Providers in src/test/…/dataproviders 5. Cover your tests with data providers 84
INSTRUCTION 6. Setup project settings in: • test. properties • log 4 j. properties • Init. Tests 7. Add your tests running in CI (e. g. Jenkins) using maven cmd line. Add different test runs with parameters in CI if you need this 8. Create parallel tests run(s) using testng xml put them in src/test/resources 85
FOR BUSINESS 86
JDI BENEFITS • Write test code faster up to 5 times • Average result around 2. 8 times • 4. 7 times speedup on the project with standard implementation • Produce less amount of test code (loc) up to 3 times • Average result around 2. 1 times • 2. 8 times reduction on the project with standard implementation • Achieve higher clearness of tests • Decrease of support time for test projects • Lowering of project entry barrier for newcomers • Complete projects with higher quality • Based on 70 % answers in survey 87
JDI BENEFITS • Reuse investments from one Project on another • Based on 5 years of work and more than 30 projects that already use JDI • Save up to 80% test effort by migrating tests to other Platforms • Based estimated average scope reductions for all test process stages • Example: migrate Web tests to Mobile platform • Can be used in most of projects with UI Automation • Actually we have no projects where JDI is not applicable. The only reason why not all of our projects use JDI is Client requirements • Save up to 30 -40% money from whole test process • Based on average calculation of scope reductions for all test process stages 88
FUTURE 89
LOG IN BDD STYLE Product. Page. Product. Type. select( «jacket» ); Product. Page. Price. select( « 500$» ); Product. Page. Colors. check( «black» , «white» ); I select ‘jacket’ Product. Type on Product. Page I select ‘ 500$’ Price on Product. Page I check ‘black’ and ‘white’ Colors on Product. Page 90
GENERATED PAGE OBJECTS • Chrome plugin • Get ui elements to page object in browser • Auto generation public class Login. Form extends Form<User> { @Find. By (css=“. login”) public Text. Field login; @Find. By (css=“. psw”) public Text. Field password; } @Find. By (css=“. submit”) public Button login; 91
SERVICES PAGE OBJECTS @Service. Domain(“http: //service. com”) public class Service. Example { @GET (“/color/get”) public Rest. Method get. Color; @POST (“/color/change/100”) public Rest. Method change. Color; } Auto generation by WSDL 92
DB TESTING SUPPORT 93
SIMPLE TESTS GENERATOR 94
SUPPORT MAIN UI DEV FRAMEWORKS 95
PERFORMANCE / STATISTIC 96
SNIFF HTTP REQUESTS 97
SUPPORT JS / PHYTON 98
GOOD PRACTICES 99
REMEMBER Test Scenarios should be clear for understanding. Every man can read and understand them (client, test engineer, analyst): a) Move all things not related to scenario out in separate modules. Common test parts move in to before/after test. Combine 3 or more asserts followed one by one in one step check b) Limit your test scenarios with 10 -15 lines. Test class with 150 -200. In other case You can logically split your test classes in to several suits with high chances c) Tests names should clearly say about their essence d) Each test scenario line should represent one business step e) All test checks/asserts should be in test scenario as step. You should not hide them in to steps 100
REMEMBER Test scenarios are useless without right test infrastructure: a) Tests should run on regular basement on CI. Your test scenarios should be ready to get settings from command line (environment domain, test group, browser etc. ) b) Test suit should work stable on stable build. If some tests falls randomly. You must fix them or temporarily remove them from test suit c) Tests should represent all info about test run in suitable format. They should provide detailed enough log about scenario steps and provide visible reports 101
REMEMBER • Tests should be independent. Each test should be run separetly. Use preconditions in order to move test to expected state. Tests should not disturb one to another. If some tests should use common data then move them in separate group • Never use Thread. Sleep. Wait some application state (page load, end of ajax…) or next element appearance instead • Use your brain and get pleasure from testing. If automation testing not make you happy possibly you doing something wrong. Think about it 102
ENJOY 103
CONTACTS • UI Objects • typified Elements • typified Objects • Entity Driven testing • Interfaces http: //jdi. epam. com/ https: //vk. com/jdi_framework roman. Iovlev roman_iovlev@epam. com https: //github. com/epam/JDI 104
Roman Iovlev - Test UI with JDI - Selenium Camp.pptx