PACIFIC NW SOFTWARE QUALITY CONFERENCE Automating Restaurant PointofSale

  • Slides: 30
Download presentation
PACIFIC NW SOFTWARE QUALITY CONFERENCE Automating Restaurant Point-of-Sale Testing With Selenium Web. Driver JEFFREY

PACIFIC NW SOFTWARE QUALITY CONFERENCE Automating Restaurant Point-of-Sale Testing With Selenium Web. Driver JEFFREY PAYNE Director of Engineering, Granbury Solutions OCTOBER 18, 2016

PACIFIC NW SOFTWARE QUALITY This Is a War Story • We are not consultants.

PACIFIC NW SOFTWARE QUALITY This Is a War Story • We are not consultants. • We had a complicated testing problem. • We needed a solid architectural foundation. • But had to be practical about architecture. • Java Ecosystem. • Use proven tools. • Spring, Selenium Web. Driver, Bamboo, Jenkins. CONFERENCE

PACIFIC NW This Is the Battlefield SOFTWARE QUALITY CONFERENCE

PACIFIC NW This Is the Battlefield SOFTWARE QUALITY CONFERENCE

 • • Firefly – Legacy POS System Had to be replaced. Restaurants are

• • Firefly – Legacy POS System Had to be replaced. Restaurants are more complex than you think. Complicated Business Rules Developers are optimists. Incremental Rewrite Online Ordering Integration PACIFIC NW All Things Pass Away SOFTWARE QUALITY CONFERENCE

 • Develop a Cross Product Testing Tool • Use an abstraction layer to

• Develop a Cross Product Testing Tool • Use an abstraction layer to separate test logic from product specific implementations. • Hipster friendly JSON • Quickly add new edge cases. • Integrate all the things. • Integrate into CI process. PACIFIC NW The Battle Plan SOFTWARE QUALITY CONFERENCE

 • • • It can’t be done. You need “real” engineers. Don’t waste

• • • It can’t be done. You need “real” engineers. Don’t waste our best people on quality. Too many things to test. Too many configuration options. Too many integration partners. But Quality is Free, I Tell You! Free! Investing in quality takes cost out of other parts of the organization. PACIFIC NW And There Was Much Pearl Clutching SOFTWARE QUALITY CONFERENCE

 • It has layers! • JUnit per wisdom of the ancients. • Heavy

• It has layers! • JUnit per wisdom of the ancients. • Heavy base test class. • JSON scenarios. • JSON environment configuration. • Parsed with Spring assisted Jackson. • Product drivers. • Command handlers. • Page objects. • Graybox. PACIFIC NW Presenting Crossfire SOFTWARE QUALITY CONFERENCE

@Service public class ARandom. Component { public String get. Something() { return "something"; }

@Service public class ARandom. Component { public String get. Something() { return "something"; } } @Component public class AComponent. User { @Autowired private ARandom. Component component; public String get. Something() { return component. get. Something(); } } PACIFIC NW A Dangerously Brief Intro To Spring SOFTWARE QUALITY CONFERENCE

 • Loads a scenario file from the classpath. @Category(Sanity. Test. class) public class

• Loads a scenario file from the classpath. @Category(Sanity. Test. class) public class Simple. Order. Submit. Test extends Cross. Fire. Test. Support { @Override protected String[] get. Scenarios() { return new String[]{"order/simple-order-submit"}; } } PACIFIC NW The JUnit Test Case SOFTWARE QUALITY CONFERENCE

{ } "name": ”Login Test", "commands": [ { "command": "login", "login. Id": "916845", "success.

{ } "name": ”Login Test", "commands": [ { "command": "login", "login. Id": "916845", "success. Expected": true, "expected. Login. Name": "Firefly", "station. Name": "Tabitha", "job. Type": "Owner” } ] PACIFIC NW A Scenario File SOFTWARE QUALITY CONFERENCE

A HUMBLE DEMO PACIFIC NW SOFTWARE QUALITY CONFERENCE

A HUMBLE DEMO PACIFIC NW SOFTWARE QUALITY CONFERENCE

{ } "command": "menu-item-select", "item. Display. Name": "Cheese Pizza", "expected. Item. Price": "7. 00",

{ } "command": "menu-item-select", "item. Display. Name": "Cheese Pizza", "expected. Item. Price": "7. 00", "expected. Total": "5. 30", "item. Serial": 0, "success. Expected": true PACIFIC NW A Command in JSON Form SOFTWARE QUALITY CONFERENCE

@Component public class Menu. Item. Select. Command extends Abstract. Pos. Command{ private String item.

@Component public class Menu. Item. Select. Command extends Abstract. Pos. Command{ private String item. Display. Name; private String size. Display. Name; private Big. Decimal expected. Item. Price; private Integer item. Serial; private Big. Decimal expected. Total; //getters and setters @Override public String get. Command() { return "menu-item-select"; } } PACIFIC NW A Command Class SOFTWARE QUALITY CONFERENCE

PACIFIC NW Parsing Commands SOFTWARE QUALITY CONFERENCE • Custom Jackson Deserializer @Post. Construct public

PACIFIC NW Parsing Commands SOFTWARE QUALITY CONFERENCE • Custom Jackson Deserializer @Post. Construct public void after. Properties. Set() throws Exception { for (Command command : context. get. Beans. Of. Type(Command. class). values()) { command. Map. put(command. get. Command(), command. get. Class()); } }

Object. Mapper mapper = new Object. Mapper(); Simple. Module module = new Simple. Module();

Object. Mapper mapper = new Object. Mapper(); Simple. Module module = new Simple. Module(); module. add. Deserializer(Command. class, command. Deserializer); mapper. register. Module(module); Input. Stream in. Stream = this. get. Class(). get. Resource. As. Stream("/scenarios/" + scenario. File + ". json"); return mapper. read. Value(in. Stream, Test. Scenario. class); PACIFIC NW Parsing Scenarios SOFTWARE QUALITY CONFERENCE

{ } "host. Name": "nope. grsthrive. com", "close. Browser": true, "clear. All. Station": true,

{ } "host. Name": "nope. grsthrive. com", "close. Browser": true, "clear. All. Station": true, "default. Login. Id": "XXX", "gray. Box. Enabled": true, "ticket. Stream. Host": "https: //nicetry. grsthrive. com", "ticket. Stream. Api. Id": "XXXXXXX", "ticket. Stream. Secret. Key": "XXXXXXXXXX", "browser. Profile": "default", "browsers": ["FIREFOX", "CHROME", "SAFARI"], "products": ["THRIVE"], "olo": { "product": "SLICE", "hostname": "olo-dev. grsthrive. com", "account. Id": "1" } PACIFIC NW Environment Configuration SOFTWARE QUALITY CONFERENCE

 • Sets target host. • Sets associated online ordering system. • Sets target

• Sets target host. • Sets associated online ordering system. • Sets target browsers. • Sets target products. • Changed via command line arguments. • By configuring CI very carefully we test on real hardware. • Even Windows. • I prefer Mac. PACIFIC NW Environment Configuration Explained SOFTWARE QUALITY CONFERENCE

protected Web. Driver resolve. Web. Driver(Target. Environment env, Browser browser) { switch (browser) {

protected Web. Driver resolve. Web. Driver(Target. Environment env, Browser browser) { switch (browser) { case HEADLESS: return new Html. Unit. Driver(); case FIREFOX: return new Firefox. Profile (); case SAFARI: return new Safari. Driver(); case CHROME: return new Chrome. Driver(); case IE: return new Internet. Explorer. Driver(); } return null; } PACIFIC NW Resolving The Web. Driver SOFTWARE QUALITY CONFERENCE

PACIFIC NW The Magical Product Driver SOFTWARE QUALITY CONFERENCE protected Cross. Fire. Product. Driver

PACIFIC NW The Magical Product Driver SOFTWARE QUALITY CONFERENCE protected Cross. Fire. Product. Driver resolve. Product. Driver(Product product) throws Exception { Collection<Cross. Fire. Product. Driver> drivers = application. Context. get. Beans. Of. Type(Cross. Fire. Product. Driver. class). values(); for (Cross. Fire. Product. Driver driver : drivers) { if (driver. get. Product() == product) { return driver; } } return null; }

PACIFIC NW The Magical Product Driver SOFTWARE QUALITY CONFERENCE protected Cross. Fire. Product. Driver

PACIFIC NW The Magical Product Driver SOFTWARE QUALITY CONFERENCE protected Cross. Fire. Product. Driver resolve. Product. Driver(Product product) throws Exception { Collection<Cross. Fire. Product. Driver> drivers = application. Context. get. Beans. Of. Type(Cross. Fire. Product. Driver. class). values(); for (Cross. Fire. Product. Driver driver : drivers) { if (driver. get. Product() == product) { return driver; } } return null; }

for (Command command : scenario. get. Commands()) { driver. execute(command, env, web. Driver) }

for (Command command : scenario. get. Commands()) { driver. execute(command, env, web. Driver) } PACIFIC NW The Command Execution Loop SOFTWARE QUALITY CONFERENCE

public interface Command. Handler<C extends Command> { public Product get. Product(); public Class<C> get.

public interface Command. Handler<C extends Command> { public Product get. Product(); public Class<C> get. Command. Class(); public void execute(C cmd, Target. Environment env, Web. Driver web. Driver); } PACIFIC NW The Command Handler Interface SOFTWARE QUALITY CONFERENCE

protected Command. Handler resolve. Handler(Command command) throws Exception { Collection<Command. Handler> handlers = context.

protected Command. Handler resolve. Handler(Command command) throws Exception { Collection<Command. Handler> handlers = context. get. Beans. Of. Type(Command. Handler. class). values(); for (Command. Handler handler : handlers) { if ( (handler. get. Product() == get. Product()) && (handler. get. Command. Class(). is. Assignable. From(command. get. Class()))) { return handler; } } return null; } PACIFIC NW Finding Command Handlers SOFTWARE QUALITY CONFERENCE

@Component public class Menu. Item. Select. Command. Handler extends Abstract. Command. Handler<Menu. Item. Select.

@Component public class Menu. Item. Select. Command. Handler extends Abstract. Command. Handler<Menu. Item. Select. Command>{ @Autowired private Virtual. Ticket virtual. Ticket; @Autowired private Menu menu; …. . } PACIFIC NW An Actual Command Handler SOFTWARE QUALITY CONFERENCE

PACIFIC NW The Mighty Execute Method SOFTWARE public void execute(Menu. Item. Select. Command cmd,

PACIFIC NW The Mighty Execute Method SOFTWARE public void execute(Menu. Item. Select. Command cmd, Target. Environment env, Web. Driver driver) { try { menu. select. Item(driver, cmd. get. Item. Display. Name()); if(cmd. get. Size. Display. Name() != null) { menu. select. Size(driver, cmd. get. Size. Display. Name()); } if(cmd. get. Expected. Total() != null) { virtual. Ticket. verify. Total(driver, cmd. get. Expected. Total()); } if(cmd. get. Expected. Item. Price() != null) { virtual. Ticket. wait. Item. Until. Value( driver, cmd. get. Item. Serial(), cmd. get. Expected. Item. Price()); } } catch (Exception e) { logger. error(e. get. Message()); } if (cmd. is. Success. Expected()) { assert. Success(driver, cmd); } } QUALITY CONFERENCE

@Component public class Menu extends Abstract. Page. Object { } public void select. Item(Web.

@Component public class Menu extends Abstract. Page. Object { } public void select. Item(Web. Driver driver, String display. Name) { boolean found = false; if(selected. Menu. Id > 0) { found = select. Item. From. Selected. Menu(driver, display. Name); } if(!found) { List<Web. Element> all. Item. Buttons = driver. find. Elements(By. tag. Name("button")); go. To. Item(driver, all. Item. Buttons, display. Name); } } PACIFIC NW A Page Object SOFTWARE QUALITY CONFERENCE

PACIFIC NW A Look Back And Piling On SOFTWARE QUALITY CONFERENCE • From JSON

PACIFIC NW A Look Back And Piling On SOFTWARE QUALITY CONFERENCE • From JSON to Web. Driver just like that. • Domain Specific Language • Once the command library is large enough, you don’t need to write Java code to add tests. • Simulating Printers • Cash Drawers • Caller ID Integration • Credit Card Processing

 • • • You are a real developer. You get to use architecture,

• • • You are a real developer. You get to use architecture, too. Complex systems need complex systems to test them. Don’t let them tell you it can’t be automated. Turn to robots for help. PACIFIC NW You Deserve Architecture SOFTWARE QUALITY CONFERENCE

Danny Roozen, Thr!ve POS Team Lead Muhit Mustakim, SDET Gillian Schweighardt, QA Analyst Kevin

Danny Roozen, Thr!ve POS Team Lead Muhit Mustakim, SDET Gillian Schweighardt, QA Analyst Kevin Nichols, QA Analyst Scott Casey, QA Analyst Matthew Martin, Dev. Ops Engineer Josiah Neiedrauer, Dev. Ops Engineer Rob De. Malloc, SDET PACIFIC NW The Team That Built It SOFTWARE QUALITY CONFERENCE

Granbury Solutions: http: //www. granburyrs. com/ Email: jpayne@granburyrs. com PACIFIC NW Contact Me SOFTWARE

Granbury Solutions: http: //www. granburyrs. com/ Email: jpayne@granburyrs. com PACIFIC NW Contact Me SOFTWARE QUALITY CONFERENCE