Upload
jan-molak
View
112
Download
1
Embed Size (px)
Citation preview
@JanMolak @Wakaleo#Devoxx #SerenityJS
@JanMolak @Wakaleo#Devoxx #SerenityJS
@JanMolak @Wakaleo#Devoxx #SerenityJS
Jan Molak, John Smart:
Next GenerationAcceptance Testing
@JanMolak @Wakaleo#Devoxx #SerenityJS
acceptance tests that help deliver working software that matters
@JanMolak @Wakaleo#Devoxx #SerenityJS
what’s the root cause ofmost software defects?
@JanMolak @Wakaleo#Devoxx #SerenityJS
ambiguous, unclear and incorrectrequirements
@JanMolak @Wakaleo#Devoxx #SerenityJS
44-80%of all software defectssource:- 44% - “Out of Control - Why Control Systems Go Wrong and How to Prevent Failure”- 56% - “An Information Systems Manifesto”- 80% - “Requirements: A quick and inexpensive way to improve testing”
@JanMolak @Wakaleo#Devoxx #SerenityJS
Behaviour-Driven Development
@JanMolak @Wakaleo#Devoxx #SerenityJS
Domain-Driven DesignBehaviour-Driven Development
@JanMolak @Wakaleo#Devoxx #SerenityJS
User-Centred DesignDomain-Driven Design
Behaviour-Driven Development
@JanMolak @Wakaleo#Devoxx #SerenityJS
reliablescalable
actionable
acceptance tests that are:
@JanMolak @Wakaleo#Devoxx #SerenityJS
example
feature → scenario
@JanMolak @Wakaleo#Devoxx #SerenityJS
Feature:Filterthelisttofinditemsofinterest InordertolimitthecognitiveloadJameswouldliketofilterhistodolisttoonlyshowitemsofinterest
@JanMolak @Wakaleo#Devoxx #SerenityJS
Scenario:ViewingActiveitemsonlyGivenJameshasalistwithWalkthedog,GetacoffeeAndhecompletesWalkthedogWhenhefiltershislisttoshowonlyActivetasksThenhistodolistshouldcontainGetacoffee
@JanMolak @Wakaleo#Devoxx #SerenityJS
automation, take #1 “a test script”
@JanMolak @Wakaleo#Devoxx #SerenityJS
GivenJameshasalistwithWalkthedog,Getacoffee——————————————————————————————————————————————————————this.Given(/^.*hasalistwith(.*)$/,(items,done)=>{
done();});
@JanMolak @Wakaleo#Devoxx #SerenityJS
GivenJameshasalistwithWalkthedog,Getacoffee——————————————————————————————————————————————————————this.Given(/^.*hasalistwith(.*)$/,(items,done)=>{browser.get('http://todomvc.com/examples/angularjs/');
items.split(‘,’).forEach(item=>{element(by.id(‘new-todo’)).sendKeys(item);element(by.id(‘new-todo’)).sendKeys(protractor.Key.ENTER);});
done();});
@JanMolak @Wakaleo#Devoxx #SerenityJS
GivenJameshasalistwithWalkthedog,Getacoffee——————————————————————————————————————————————————————this.Given(/^.*hasalistwith(.*)$/,(items,done)=>{browser.get('http://todomvc.com/examples/angularjs/');
items.split(‘,’).forEach(item=>{element(by.id(‘new-todo’)).sendKeys(item);element(by.id(‘new-todo’)).sendKeys(protractor.Key.ENTER);});
done();});
@JanMolak @Wakaleo#Devoxx #SerenityJS
automation, take #2 “a re-structured test script”
@JanMolak @Wakaleo#Devoxx #SerenityJS
GivenJameshasalistwithWalkthedog,Getacoffee——————————————————————————————————————————————————————this.Given(/^.*hasalistwith(.*)$/,(items,done)=>{lettodoList=newTodoListPage();
todoList.get();
items.split(‘,’).forEach(item=>{todoList.add(item);});
done();});
@JanMolak @Wakaleo#Devoxx #SerenityJS
classTodoListPage{get(){browser.get('http://todomvc.com/examples/angularjs/');}add(item:string){element(by.id(‘new-todo’)).sendKeys(item); element(by.id('new-todo')).sendKeys(protractor.Key.ENTER); }complete(item:string){element(by.xpath('//*[@class="view"andcontains(.,"'+item+'")]'+ '//input[@type="checkbox"]')).click();}//…}
@JanMolak @Wakaleo#Devoxx #SerenityJS
classTodoListPage{get(){browser.get('http://todomvc.com/examples/angularjs/');}add(item:string){element(by.id(‘new-todo’)).sendKeys(item); element(by.id('new-todo')).sendKeys(protractor.Key.ENTER); }complete(item:string){element(by.xpath('//*[@class="view"andcontains(.,"'+item+'")]'+ '//input[@type="checkbox"]')).click();}//…}
@JanMolak @Wakaleo#Devoxx #SerenityJS
automation, take #3 “a screenplay”
@JanMolak @Wakaleo#Devoxx #SerenityJS
hierarchical task analysis
@JanMolak @Wakaleo#Devoxx #SerenityJS
hierarchical task analysis
actor
@JanMolak @Wakaleo#Devoxx #SerenityJS
hierarchical task analysis
goal
@JanMolak @Wakaleo#Devoxx #SerenityJS
hierarchical task analysis
tasks
@JanMolak @Wakaleo#Devoxx #SerenityJS
hierarchical task analysis
interactions
@JanMolak @Wakaleo#Devoxx #SerenityJS
Feature:FilterthelisttofinditemsofinterestInordertolimitthecognitiveloadJameswouldliketofilterhistodolisttoonlyshowitemsofinterest
Scenario:ViewingActiveitemsonlyGivenJameshasalistwithWalkthedog,GetacoffeeAndhecompletesWalkthedogWhenhefiltershislisttoshowonlyActivetasksThenhistodolistshouldcontainGetacoffee
@JanMolak @Wakaleo#Devoxx #SerenityJS
Feature:FilterthelisttofinditemsofinterestInordertolimitthecognitiveloadJameswouldliketofilterhistodolisttoonlyshowitemsofinterest
Scenario:ViewingActiveitemsonlyGivenJameshasalistwithWalkthedog,GetacoffeeAndhecompletesWalkthedogWhenhefiltershislisttoshowonlyActivetasksThenhistodolistshouldcontainGetacoffee
actor
@JanMolak @Wakaleo#Devoxx #SerenityJS
Feature:FilterthelisttofinditemsofinterestInordertolimitthecognitiveloadJameswouldliketofilterhistodolisttoonlyshowitemsofinterest
Scenario:ViewingActiveitemsonlyGivenJameshasalistwithWalkthedog,GetacoffeeAndhecompletesWalkthedogWhenhefiltershislisttoshowonlyActivetasksThenhistodolistshouldcontainGetacoffee
actor goal
@JanMolak @Wakaleo#Devoxx #SerenityJS
Scenario:ViewingActiveitemsonlyGivenJameshasalistwithWalkthedog,GetacoffeeAndhecompletesWalkthedogWhenhefiltershislisttoshowonlyActivetasksThenhistodolistshouldcontainGetacoffee
actor goal
tasks
@JanMolak @Wakaleo#Devoxx #SerenityJS
ToviewActiveitemsonly,Jamesattemptsto:
Startwithalistcontaining:Walkthedog,GetacoffeeCompleteatodoitemcalled:WalkthedogFilterlisttoshowonlyActivetasksExpecttosee:Getacoffee
actor goal
tasks
@JanMolak @Wakaleo#Devoxx #SerenityJS
ToviewActiveitemsonly,Jamesattemptsto:
Startwithalistcontaining:Walkthedog,GetacoffeeOpenbrowseron‘todomvc.com/examples/angularjs/'ResizebrowserwindowtomaximumAddatodoitemcalled‘Walkthedog’Addatodoitemcalled‘Getacoffee’...
actor goal
tasks
@JanMolak @Wakaleo#Devoxx #SerenityJS
ToviewActiveitemsonly,Jamesattemptsto:
Startwithalistcontaining:Walkthedog,GetacoffeeOpenbrowseron‘todomvc.com/examples/angularjs/'ResizebrowserwindowtomaximumAddatodoitemcalled‘Walkthedog’Addatodoitemcalled‘Getacoffee’Enterthevalue‘Getacoffee’HittheEnterkey...
actor goal tasks inter-
actions
@JanMolak @Wakaleo#Devoxx #SerenityJS
ToviewActiveitemsonly,Jamesattemptsto:
Startwithalistcontaining:Walkthedog,GetacoffeeOpenbrowseron‘todomvc.com/examples/angularjs/'ResizebrowserwindowtomaximumAddatodoitemcalled‘Walkthedog’Addatodoitemcalled‘Getacoffee’Enterthevalue‘Getacoffee’HittheEnterkey...
@JanMolak @Wakaleo#Devoxx #SerenityJS
ToviewActiveitemsonly,Jamesattemptsto:
Start.withATodoListContaining(‘Walkthedog’,…)Open.browserOn(‘todomvc.com/examples/angularjs/’)ResizeBrowserWindow.toMaximum()AddATodoItem.called(‘Walkthedog’)AddATodoItem.called(‘Getacoffee’)Enter.theValue(‘Getacoffee’).into(TodoList.New_Todo_Field).thenHit(protractor.Key.Enter)
@JanMolak @Wakaleo#Devoxx #SerenityJS
ToviewActiveitemsonly,Jamesattemptsto:
Start.withATodoListContaining(‘Walkthedog’,…)Open.browserOn(‘todomvc.com/examples/angularjs/’)ResizeBrowserWindow.toMaximum()AddATodoItem.called(‘Walkthedog’)AddATodoItem.called(‘Getacoffee’)Enter.theValue(‘Getacoffee’).into(TodoList.New_Todo_Field).thenHit(protractor.Key.Enter)
@JanMolak @Wakaleo#Devoxx #SerenityJS
Serenity/JS Screenplay Pattern
@JanMolak @Wakaleo#Devoxx #SerenityJS
letjames=Actor.named(‘James’);actor
@JanMolak @Wakaleo#Devoxx #SerenityJS
letjames=Actor.named(‘James’).whoCan(BrowseTheWeb.using(protractor.browser));
actor has
abilities
@JanMolak @Wakaleo#Devoxx #SerenityJS
james.attemptsTo(Start.withATodoListContaining(items));
actor performs
tasks
@JanMolak @Wakaleo#Devoxx #SerenityJS
this.Given(/^.*hasalistwith(.*)$/,(items)=>{returnjames.attemptsTo(Start.withATodoListContaining(items));});
actor performs
tasks
@JanMolak @Wakaleo#Devoxx #SerenityJS
exportclassStartimplementsTask{performAs(actor:PerformsTasks):PromiseLike<void>{returnactor.attemptsTo(Open.browserOn('/examples/angularjs/'),ResizeBrowserWindow.toMaximum(),AddTodoItems.called(this.initialItems));}}
tasks consist of
tasks
@JanMolak @Wakaleo#Devoxx #SerenityJS
exportclassAddATodoItemimplementsTask{performAs(actor:PerformsTasks):PromiseLike<void>{returnactor.attemptsTo(Enter.theValue(‘Walkthedog’).into(TodoList.New_Todo_Field),Hit.the(protractor.Key.Enter).into(ToDoList.New_Todo_Field) ); }}
tasks consist of
inter-actions
@JanMolak @Wakaleo#Devoxx #SerenityJS
exportclassAddATodoItemimplementsTask{
@step('{0}addsatodoitemcalled"#name"')performAs(actor:PerformsTasks):PromiseLike<void>{//…}
constructor(privatename:string){}}
tasks can be
annotated
@JanMolak @Wakaleo#Devoxx #SerenityJS
to create powerful reports
@JanMolak @Wakaleo#Devoxx #SerenityJS
lights, camera,Demo!
@JanMolak @Wakaleo#Devoxx #SerenityJS
github.com/jan-molak/serenity-js