SlideShare a Scribd company logo
@juliaviluhina @yashaka
Better Bullshit Driven Development
@juliaviluhina @yashaka
automician.com seleniumcourses.com
About
@juliaviluhina @yashaka
Better Bullshit Driver Development
Preface
Plan
Preface: Classic BDD & xUnit examples
BDD Intro
Better BDD with xUnit + Allure
Q&A
BDD?
xUnit style
public class DiasporaTest extends BaseTest {

LoginPage loginPage = new LoginPage();

NewPost newPost = new NewPost();

Stream stream = new Stream();



@Test

public void shareMessage() {

loginPage.open();

loginPage.signIn(Users.Selenide.username, Users.Selenide.password);

newPost.start();

newPost.write("Selenide 4.2 released!");

newPost.share();

stream.shouldHavePostWithText(0, "Selenide 4.2 released!");

}

}
xUnit style
public class DiasporaTest extends BaseTest {

LoginPage loginPage = new LoginPage();

NewPost newPost = new NewPost();

Stream stream = new Stream();



@Test

public void shareMessage() {

loginPage.open();

loginPage.signIn(Users.Selenide.username, Users.Selenide.password);

newPost.start();

newPost.write("Selenide 4.2 released!");

newPost.share();

stream.shouldHavePostWithText(0, "Selenide 4.2 released!");

}

}
BDD style (option 1)
@defaults

Feature: Diaspora



Scenario: Share message

Given I open login page

And I do sign in with credentials: 'selenide', 'xxxxxxxx'

When I start new post

And write new post message: 'Selenide 4.2 is released!'

And share new post

Then stream should have post with index '1' of text 'Selenide 4.2 is
released!'
BDD style (option 1)
public class DiasporaStepdefs {

LoginPage loginPage = new LoginPage();

NewPost newPost = new NewPost();

Stream stream = new Stream();



@Given("^I open login page$")

public void I_open_login_page(){

loginPage.open();

}





@And("^I do sign in with credentials: '(.+)', '(.+)'$")

public void I_do_sign_in_with_credentials_selenide_yagniyagni(String
username, String password) {

loginPage.signIn(username, password);

}
...
BDD style (option 1)
...

@When("^I start new post$")

public void I_start_new_post(){

newPost.start();

}



@And("^write new post message: '(.+)'$")

public void write_new_post_message_Selenide_is_released_(String text){

newPost.write(text);

}
...
BDD style (option 1)
...
@And("^share new post$")

public void share_new_post() {

newPost.share();

}



@Then("^stream should have post with index '( d+)' of text '(.+)'$")

public void
stream_should_have_post_with_index_of_text_Selenide_is_released_(int
index, String text) {

stream.shouldHavePostWithText(index-1, text);

}

}
BDD style (option 2)
@defaults

Feature: Diaspora



Scenario: Share message

Given I signed in from login page with credentials: 'selenide', 'xxxx'

When I publish new post: 'Selenide 4.2 is released!'

Then I should see new post 'Selenide 4.2 is released!' in the top of
stream
BDD style (option 2)
public class DiasporaStepdefs {

LoginPage loginPage = new LoginPage();

NewPost newPost = new NewPost();

Stream stream = new Stream();



@Given("^I signed in from login page with credentials: '(.+)', '(.+)'$")

public void
I_signed_in_from_login_page_with_credentials_selenide_yagniyagni(String
username, String password) {

loginPage.open();

loginPage.signIn(username, password);

}
...
BDD style (option 2)
...
@When("^I publish new post: '(.+)'$")

public void I_publish_new_post_Selenide_is_released_(String text) {

newPost.start();

newPost.write(text);

newPost.share();

}



@Then("^I should see new post '(.+)' in the top of stream$")

public void
I_should_see_new_post_Selenide_is_released_in_the_top_of_stream(String
text) {

stream.shouldHavePostWithText(0, text);

}

}
BDD Intro
= ?BDD
= ?
human readable
scenarios
…
BDD
= ?
human readable
scenarios
pretty reports
BDD
= ...
human readable
scenarios
pretty reports
BDD
= Optimised
ATDD
BDD
=BDD Optimised
ATDD
giving as a bonus:
readable scenarios and
reports
= Optimised
ATDD
=
?
BDD
= Optimised
ATDD
=
Devs write tests rst
BDD
= Optimised
ATDD
=
Devs write acceptance
tests rst
BDD
= Optimised
ATDD
=
Devs write acceptance
tests rst
based on scenarios
already written by BA/PO
BDD
= Optimised
ATDD
=
Devs write acceptance
tests rst
based on scenarios
already written by BA/PO
BDD
=BDD Optimised
ATDD
=
Devs write acceptance
tests rst
based on scenarios
already written by BA/PO
unbiased thinking of end
product
doing things once
(reqs are 2 in 1 - are
already automatable)
=BDD Optimised
ATDD
=
Devs write acceptance
tests rst
based on scenarios
already written by BA/PO
unbiased thinking of end
product
doing things once
(reqs are 2 in 1 - are
already automatable)
Optimised
ATDD
=
Devs write acceptance
tests rst
based on scenarios
already written by BA/PO
unbiased thinking of end
product
doing things once
(reqs are 2 in 1 - are
already automatable)
Behaviour Driven Development
Optimised
ATDD
=
Devs write acceptance
tests rst
based on scenarios
already written by BA/PO
unbiased thinking of end
product
doing things once
(reqs are 2 in 1 - are
already automatable)
Beh?viour Driven Development
Optimised
ATDD
=
Devs write acceptance
tests rst
based on scenarios
already written by BA/PO
Automation engineers
write tests after.
adding extra “readable
scenarios” layer for “good
reports”
Beh?viour Driven Development
vs
vs
Optimised
ATDD
=
Devs write acceptance
tests rst
based on scenarios
already written by BA/PO
Automation engineers
write tests after.
adding extra “readable
scenarios” layer for “good
reports”
Bullshit Driven Development
vs
vs
WTF?
adding additional limited
pseudo-programming layer
just to make tests readable
and with good reports?
WTF?
adding additional limited
pseudo-programming layer
just to make tests readable
and with good reports?
Better “Bullshit” Driven Development
without additional limited pseudo programming layers ;)
Readable xUnit
pom.xml with just xUnit + Selenide
<dependencies>

<dependency>

<groupId>com.codeborne </groupId>

<artifactId>selenide </artifactId>

<version>4.2 </version>

<scope>test </scope>

</dependency>

<dependency>

<groupId>junit </groupId>

<artifactId>junit </artifactId>

<version>4.12 </version>

</dependency>

</dependencies>
xUnit + PageObject with readable steps
public class DiasporaTest extends BaseTest {

LoginPage loginPage = new LoginPage();

NewPost newPost = new NewPost();

Stream stream = new Stream();



@Test

public void shareMessage() {

loginPage.open();

loginPage.signIn(Users.Selenide.username, Users.Selenide.password);

newPost.start();

newPost.write("Selenide 4.2 released!");

newPost.share();

stream.shouldHavePostWithText(0, "Selenide 4.2 released!");

}

}
xUnit + PageObject with readable steps
public class DiasporaTest extends BaseTest {

LoginPage loginPage = new LoginPage();

NewPost newPost = new NewPost();

Stream stream = new Stream();



@Test

public void shareMessage() {

loginPage.open();

loginPage.signIn(Users.Selenide.username, Users.Selenide.password);

newPost.start();

newPost.write("Selenide 4.2 released!");

newPost.share();

stream.shouldHavePostWithText(0, "Selenide 4.2 released!");

}

}
xUnit + PageObject with readable steps
public class DiasporaTest extends BaseTest {

LoginPage loginPage = new LoginPage();

NewPost newPost = new NewPost();

Stream stream = new Stream();



@Test

public void shareMessage() {

loginPage.open();

loginPage.signIn(Users.Selenide.username, Users.Selenide.password);

newPost.start();

newPost.write("Selenide 4.2 released!");

newPost.share();

stream.shouldHavePostWithText(0, "Selenide 4.2 released!");

}

}
xUnit + PageObject with readable steps
public class LoginPage {



public void open() {

Selenide.open("/users/sign_in");

}



public void signIn(String username, String password) {

Form form = new Form($("#new_user"));

form.set("USERNAME", username);

form.set("PASSWORD", password);

form.submit();

}

}
xUnit + PageObject with readable steps
Report :(
Better xUnit reports with Allure
<dependencies>
...

<dependency>

<groupId>ru.yandex.qatools.allure </groupId>

<artifactId>allure-junit-adaptor </artifactId>

<version>${allure.version} </version>

</dependency>

</dependencies>
pom.xml with Allure conguration
<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins </groupId>

<artifactId>maven-surefire-plugin </artifactId>

<version>2.19.1 </version>

<configuration>

<testFailureIgnore>false </testFailureIgnore>

<argLine>

-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"

</argLine>

<properties>

<property>

<name>listener </name>

<value>ru.yandex.qatools.allure.junit.AllureRunListener </value>

</property>

</properties>

</configuration>

<dependencies>

<dependency>

<groupId>org.aspectj </groupId>

<artifactId>aspectjweaver </artifactId>

<version>${aspectj.version} </version>

</dependency>

</dependencies>

</plugin>

...

</plugins>

</build>
<build>

<plugins>

...

<plugin>

<groupId>org.mortbay.jetty </groupId>

<artifactId>jetty-maven-plugin </artifactId>

<configuration>

<webAppSourceDirectory>${project.build.directory}/site/allure-
maven-plugin </webAppSourceDirectory>

<stopKey />

<stopPort />

</configuration>

</plugin>

</plugins>

</build>
<reporting>

<excludeDefaults>true </excludeDefaults>

<plugins>

<plugin>

<groupId>ru.yandex.qatools.allure </groupId>

<artifactId>allure-maven-plugin </artifactId>

<version>2.5 </version>

</plugin>

</plugins>

</reporting>
xUnit + PageObject with reportable @Steps :)
public class DiasporaTest extends BaseTest {

LoginPage loginPage = new LoginPage();

NewPost newPost = new NewPost();

Stream stream = new Stream();



@Test

public void shareMessage() {

loginPage.open();

loginPage.signIn(Users.Selenide.username, Users.Selenide.password);

newPost.start();

newPost.write("Selenide 4.2 released!");

newPost.share();

stream.shouldHavePostWithText(0, "Selenide 4.2 released!");

}

}
xUnit + PageObject with reportable @Steps :)
public class LoginPage {



@Step

public void open() {

Selenide.open("/users/sign_in");

}



@Step

public void signIn(String username, String password) {

Form form = new Form($("#new_user"));

form.set("USERNAME", username);

form.set("PASSWORD", password);

form.submit();

}

}
xUnit + PageObject with reportable @Steps :)
Report
xUnit + PageObject with reportable @Steps :)
Report
xUnit + PageObject with reportable @Steps :)
Report
qwerty1234
xUnit + PageObject with reportable @Steps :)
Report
qwerty1234
qwerty1234
Missed “objects info” in reports :(
public class DiasporaTest extends BaseTest {

LoginPage loginPage = new LoginPage();

NewPost newPost = new NewPost();

Stream stream = new Stream();



@Test

public void shareMessage() {

loginPage.open();

loginPage.signIn(Users.Selenide.username, Users.Selenide.password);

newPost.start();

newPost.write("Selenide 4.2 released!");

newPost.share();

stream.shouldHavePostWithText(0, "Selenide 4.2 released!");

}

}
Report :(
Missed “objects info” in reports :(
What is opened?
Where do we do signin?
What do we start?
Where?
Fixing “missed objects” with One Entry Point to PageObjects :)
public class DiasporaTest extends BaseTest {

Diaspora diaspora = new Diaspora();



@Test

public void shareMessage() {

diaspora.loginPage().open();

diaspora.loginPage()

.signIn(Users.Selenide.username, Users.Selenide.password);

diaspora.newPost().start();

diaspora.newPost().write("Selenide 4.2 released!");

diaspora.newPost().share();

diaspora.stream().shouldHavePostWithText(0, "Selenide 4.2 released!");

}

}
Fixing “missed objects” with One Entry Point to PageObjects :)
public class Diaspora {



@Step

public LoginPage loginPage() {

return new LoginPage();

}



@Step

public NewPost newPost() {

return new NewPost();

}



@Step

public Stream stream() {

return new Stream();

}
...

}
Fixing “missed objects” with One Entry Point to PageObjects :)
public class Diaspora {



@Step

public LoginPage loginPage() {

return new LoginPage();

}



@Step

public NewPost newPost() {

return new NewPost();

}



@Step

public Stream stream() {

return new Stream();

}
...

}
The simplest impl.
with
redundant objects,
not actually influencing
performance much
Fixing “missed objects” with One Entry Point to PageObjects :)
public class Diaspora {

private final LoginPage loginPage;

private final NewPost newPost;

private final Stream stream;



public Diaspora() {

this.loginPage = new LoginPage();

this.newPost = new NewPost();

this.stream = new Stream();

}



@Step

public LoginPage loginPage() {

return this.loginPage;

}

...

}
but in case
you bother…
Fixing “missed objects” with One Entry Point to PageObjects :)
public class Application {

private final LoginPage loginPage;

private final NewPost newPost;

private final Stream stream;



public Application() {

this.loginPage = new LoginPage();

this.newPost = new NewPost();

this.stream = new Stream();

}



@Step

public LoginPage loginPage() {

return this.loginPage;

}

...

}
aka Application Manager
Fixing “missed objects” with One Entry Point to PageObjects :)
public class DiasporaTest extends BaseTest {

Application app = new Application();



@Test

public void shareMessage() {

app.loginPage().open();

app.loginPage()

.signIn(Users.Selenide.username, Users.Selenide.password);

app.newPost().start();

app.newPost().write("Selenide 4.2 released!");

app.newPost().share();

app.stream().shouldHavePostWithText(0, "Selenide 4.2 released!");

}

}
aka Application Manager
Fixing “missed objects” with One Entry Point to PageObjects :)
Report
Fixing “missed objects” with One Entry Point to PageObjects :)
Report
May be a bit “too long”
while reading to nd
“logical code sentences”…
Fixing “missed objects” with One Entry Point to PageObjects :)
Report
But if consider
that “each sentence” is two lines
it becomes to make sense:)
Applying Fluent PageObject for easier scenarios …
public class DiasporaTest extends BaseTest {

Diaspora diaspora = new Diaspora();



@Test

public void shareMessage() {

diaspora.loginPage().open().signIn(

Users.Selenide.username,

Users.Selenide.password);

diaspora.newPost().start().write("Selenide 4.2 released!").share();

diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");

}

}
Applying Fluent PageObject for easier scenarios …
public class DiasporaTest extends BaseTest {

Diaspora diaspora = new Diaspora();



@Test

public void shareMessage() {

diaspora.loginPage().open().signIn(

Users.Selenide.username,

Users.Selenide.password);

diaspora.newPost().start().write("Selenide 4.2 released!").share();

diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");

}

}
Applying Fluent PageObject for easier scenarios …
public class DiasporaTest extends BaseTest {

Diaspora diaspora = new Diaspora();



@Test

public void shareMessage() {

diaspora.loginPage().open().signIn(

Users.Selenide.username,

Users.Selenide.password);

diaspora.newPost().start().write("Selenide 4.2 released!").share();

diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");

}

}
Applying Fluent PageObject for easier scenarios …
public class NewPost {

...

@Step

public NewPost start() {

this.textArea.click();

return this;

}



@Step

public NewPost write(String text) {

this.textArea.setValue(text);

return this;

}



@Step

public void share(){

this.container.find("#submit").click();

}

Applying Fluent PageObject for easier scenarios …
public class NewPost {

...

@Step

public NewPost start() {

this.textArea.click();

return this;

}



@Step

public NewPost write(String text) {

this.textArea.setValue(text);

return this;

}



@Step

public void share(){

this.container.find("#submit").click();

}

no need to be “fluent” here,
as we do not know,
where user should proceed a flow
… may lead to “missing flow” in reports :(
Report :(
Where does the sentence
start and nish?
… may lead to “missing flow” in reports :(
Report :(
Where does the sentence
start and nish?
Fixing “missed flow” with “gherkin” pseudo-steps…
public class DiasporaTest extends BaseTest {

Diaspora diaspora = new Diaspora();



@Test

public void shareMessage() {

GIVEN("Logged in from login page");

diaspora.loginPage().open().signIn(

Users.Selenide.username,

Users.Selenide.password);

WHEN("Posted new message");

diaspora.newPost().start().write("Selenide 4.2 released!").share();

THEN("Message should appear in the stream");

diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");

}

}
Fixing “missed flow” with “gherkin” pseudo-steps…
public class Gherkin {



@Step

public static void GIVEN(String step) {}



@Step

public static void AND(String step) {}



@Step

public static void WHEN(String step) {}



@Step

public static void THEN(String step) {}

}
Fixing “missed flow” with “gherkin” pseudo-steps…
Report :)
Fixing “missed flow” with “gherkin” pseudo-steps…
Report :)
Each new “code sentence”
starts with a “gherkin” keyword
Fixing “missed flow” with “gherkin” pseudo-steps…
Report
(more complicated example)
Fixing “missed flow” with “gherkin” pseudo-steps…
Report
(more complicated example)
Illustration
(more complicated example)
Fixing “missed flow” with “gherkin” pseudo-steps…
… leads sometimes to even more to readable code
THEN("Connect first cell of this column to first row from data storage");

app.testTable().row(0).cell(0).fill("1").hover();



EXPECT("Connection works by showing connected data in a cell tooltip (on
hover)");

app.testTable().toolTip()

.shouldHaveKeyRowCells("", "user", "password")

.shouldHaveValueRowCells("1", "vasya", "pupkin1234");
Implementation
(more complicated example)
… leads sometimes to not much more readable
public class DiasporaTest extends BaseTest {

Diaspora diaspora = new Diaspora();



@Test

public void shareMessage() {

GIVEN("Logged in from login page");

diaspora.loginPage().open().signIn(

Users.Selenide.username,

Users.Selenide.password);

WHEN("Posted new message");

diaspora.newPost().start().write("Selenide 4.2 released!").share();

THEN("Message should appear in the stream");

diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");

}

}
… and often redundant code :|
public class DiasporaTest extends BaseTest {

Diaspora diaspora = new Diaspora();



@Test

public void shareMessage() {

GIVEN("Logged in from login page");

diaspora.loginPage().open().signIn(

Users.Selenide.username,

Users.Selenide.password);

WHEN("Posted new message");

diaspora.newPost().start().write("Selenide 4.2 released!").share();

THEN("Message should appear in the stream");

diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");

}

}
just repeats already
readable “code”
Fixing everything:) with “gherkin” style of One Entry Point
public class DiasporaTest extends GherkinTest {



@Test

public void shareMessage() {

GIVEN().loginPage().open().signIn(

Users.Selenide.username,

Users.Selenide.password);

WHEN().newPost().start().write("Selenide 4.2 released!").share();

THEN().stream().post(0).shouldBe("Selenide 4.2 released!");

}

}
Fixing everything:) with “gherkin” style of One Entry Point
public class GherkinTest {

...

Diaspora diaspora = new Diaspora();



@Step

public Diaspora GIVEN(String ... comments) { return this.diaspora; }



@Step

public Diaspora AND(String ... comments) { return this.diaspora; }



@Step

public Diaspora WHEN(String ... comments) { return this.diaspora; }



@Step

public Diaspora THEN(String ... comments) { return this.diaspora; }

}
Fixing everything:) with “gherkin” style of One Entry Point
Report :D
Each new “code sentence”
starts with a “gherkin” keyword
Fixing everything:) with “gherkin” style of One Entry Point
THEN("Connect first cell of this column to first row from data storage")

.testTable().row(0).cell(0).fill("1").hover();



EXPECT("Connection works by showing connected data in a cell tooltip (on
hover)")

.testTable().toolTip()

.shouldHaveKeyRowCells("", "user", "password")

.shouldHaveValueRowCells("1", "vasya", "pupkin1234");
Implementation
(more complicated example)
with additional step comments when needed
Fixing everything:) with “gherkin” style of One Entry Point
Report
(more complicated example)
Summary
GIVEN
no BA writing Gherkin
AND automation engineers writing tests after
WHEN
xUnit
AND Fluent PageObjects with Allure readable @Steps
AND Gherkin style of One Entry Point (aka Application Manager)
THEN
Bullshit Driven Development is Better
Better Bullshit Driven Development with
xUnit, Fluent PageObjects, Allure @Steps, “Gherkined" One Entry Point
• all-powerful programming language over textual-pseudo-language
• full IDE support (autocompletion, auto-generate, etc.)
• 1 abstraction layer less => simpler and faster in implementation
• still fully readable and with pretty good reports
• newcomers friendly
• Just One Entry Point to all Application Model
• structured with granular Fluent PageObjects => easier to
learn&use via autocompletion
Better Bullshit Driven Development with
xUnit, Fluent PageObjects, Allure @Steps, “Gherkined" One Entry Point
• all-powerful programming language over textual-pseudo-language
• full IDE support (autocompletion, auto-generate, etc.)
• 1 abstraction layer less => simpler and faster in implementation
• still fully readable and with pretty good reports
• newcomers friendly
• Just One Entry Point to all Application Model
• structured with granular Fluent PageObjects => easier to
learn&use via autocompletion
Better Bullshit Driven Development with
xUnit, Fluent PageObjects, Allure @Steps, “Gherkined" One Entry Point
• all-powerful programming language over textual-pseudo-language
• full IDE support (autocompletion, auto-generate, etc.)
• 1 abstraction layer less => simpler and faster in implementation
• still fully readable and with pretty good reports
• newcomers friendly
• Just One Entry Point to all Application Model
• structured with granular Fluent PageObjects => easier to
learn&use via autocompletion
Better Bullshit Driven Development with
xUnit, Fluent PageObjects, Allure @Steps, “Gherkined" One Entry Point
• all-powerful programming language over textual-pseudo-language
• full IDE support (autocompletion, auto-generate, etc.)
• 1 abstraction layer less => simpler and faster in implementation
• still fully readable and with pretty good reports
• newcomers friendly
• Just One Entry Point to all Application Model
• structured with granular Fluent PageObjects => easier to
learn&use via autocompletion
Better Bullshit Driven Development with
xUnit, Fluent PageObjects, Allure @Steps, “Gherkined" One Entry Point
• all-powerful programming language over textual-pseudo-language
• full IDE support (autocompletion, auto-generate, etc.)
• 1 abstraction layer less => simpler and faster in implementation
• still fully readable and with pretty good reports
• newcomers friendly
• Just One Entry Point to all Application Model
• structured with granular Fluent PageObjects => easier to
learn&use via autocompletion
Better Bullshit Driven Development ;)
public class DiasporaTest extends GherkinTest {



@Test

public void shareMessage() {

GIVEN().loginPage().open().signIn(

Users.Selenide.username,

Users.Selenide.password);

WHEN().newPost().start().write("Selenide 4.2 released!").share();

THEN().stream().post(0).shouldBe("Selenide 4.2 released!");

}

}
Better Bullshit Driven Development ;)
More ideas
• tune Allure to report objects (via calling their toString() method)
• already possible?
• contribute?
• new Allure Feature: log object classes
• contribute?
Afterwords
There are good practices in context,
but there are no best practices.
(c) Cem Kaner, James Bach
Q&A
Thank you!
github.com/automician
automician.com
seleniumcourses.com
juliaviluhina @
@juliaviluhina @yashaka
You are welcome;)
Selene in Python
NSelene in C#
Selenide snippets in Java
Yashaka talks src code
Selenide User Guide
@juliaviluhina @yashaka

More Related Content

What's hot

Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4
DEVCON
 
Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4
DEVCON
 
Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
Simon Willison
 
Intoduction on Playframework
Intoduction on PlayframeworkIntoduction on Playframework
Intoduction on Playframework
Knoldus Inc.
 
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQUA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
Michelangelo van Dam
 
Mule esb – connecting to ms sql db
Mule esb – connecting to ms sql dbMule esb – connecting to ms sql db
Mule esb – connecting to ms sql db
Gunjan Deshmukh
 
Test and profile your Windows Phone 8 App
Test and profile your Windows Phone 8 AppTest and profile your Windows Phone 8 App
Test and profile your Windows Phone 8 App
Michele Capra
 
Developing application for Windows Phone 7 in TDD
Developing application for Windows Phone 7 in TDDDeveloping application for Windows Phone 7 in TDD
Developing application for Windows Phone 7 in TDD
Michele Capra
 
Node.js in action
Node.js in actionNode.js in action
Node.js in action
Simon Su
 
Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007
Rabble .
 
Solid Software Design Principles
Solid Software Design PrinciplesSolid Software Design Principles
Solid Software Design Principles
Jon Kruger
 
Web 6 | JavaScript DOM
Web 6 | JavaScript DOMWeb 6 | JavaScript DOM
Web 6 | JavaScript DOM
Mohammad Imam Hossain
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
David Rodenas
 
Protractor Training in Pune by QuickITDotnet
Protractor Training in Pune by QuickITDotnet Protractor Training in Pune by QuickITDotnet
Protractor Training in Pune by QuickITDotnet
QuickITDotNet Training and Services
 
Android Testing
Android TestingAndroid Testing
Android Testing
Evan Lin
 
GWT integration with Vaadin
GWT integration with VaadinGWT integration with Vaadin
GWT integration with Vaadin
Peter Lehto
 
J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012
ghnash
 
Quick Intro to Android Development
Quick Intro to Android DevelopmentQuick Intro to Android Development
Quick Intro to Android Development
Jussi Pohjolainen
 
UA Testing with Selenium and PHPUnit - ZendCon 2013
UA Testing with Selenium and PHPUnit - ZendCon 2013UA Testing with Selenium and PHPUnit - ZendCon 2013
UA Testing with Selenium and PHPUnit - ZendCon 2013
Michelangelo van Dam
 
Jquery
JqueryJquery
Jquery
adm_exoplatform
 

What's hot (20)

Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4
 
Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4
 
Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
 
Intoduction on Playframework
Intoduction on PlayframeworkIntoduction on Playframework
Intoduction on Playframework
 
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQUA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
 
Mule esb – connecting to ms sql db
Mule esb – connecting to ms sql dbMule esb – connecting to ms sql db
Mule esb – connecting to ms sql db
 
Test and profile your Windows Phone 8 App
Test and profile your Windows Phone 8 AppTest and profile your Windows Phone 8 App
Test and profile your Windows Phone 8 App
 
Developing application for Windows Phone 7 in TDD
Developing application for Windows Phone 7 in TDDDeveloping application for Windows Phone 7 in TDD
Developing application for Windows Phone 7 in TDD
 
Node.js in action
Node.js in actionNode.js in action
Node.js in action
 
Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007Introduction to Active Record - Silicon Valley Ruby Conference 2007
Introduction to Active Record - Silicon Valley Ruby Conference 2007
 
Solid Software Design Principles
Solid Software Design PrinciplesSolid Software Design Principles
Solid Software Design Principles
 
Web 6 | JavaScript DOM
Web 6 | JavaScript DOMWeb 6 | JavaScript DOM
Web 6 | JavaScript DOM
 
Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
 
Protractor Training in Pune by QuickITDotnet
Protractor Training in Pune by QuickITDotnet Protractor Training in Pune by QuickITDotnet
Protractor Training in Pune by QuickITDotnet
 
Android Testing
Android TestingAndroid Testing
Android Testing
 
GWT integration with Vaadin
GWT integration with VaadinGWT integration with Vaadin
GWT integration with Vaadin
 
J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012J query b_dotnet_ug_meet_12_may_2012
J query b_dotnet_ug_meet_12_may_2012
 
Quick Intro to Android Development
Quick Intro to Android DevelopmentQuick Intro to Android Development
Quick Intro to Android Development
 
UA Testing with Selenium and PHPUnit - ZendCon 2013
UA Testing with Selenium and PHPUnit - ZendCon 2013UA Testing with Selenium and PHPUnit - ZendCon 2013
UA Testing with Selenium and PHPUnit - ZendCon 2013
 
Jquery
JqueryJquery
Jquery
 

Viewers also liked

Excuse me, sir, do you have a moment to talk about tests in Kotlin
Excuse me, sir, do you have a moment to talk about tests in KotlinExcuse me, sir, do you have a moment to talk about tests in Kotlin
Excuse me, sir, do you have a moment to talk about tests in Kotlin
leonsabr
 
WixAutomation - Test State Pattern - Selenium Camp 2017
WixAutomation - Test State Pattern - Selenium Camp 2017WixAutomation - Test State Pattern - Selenium Camp 2017
WixAutomation - Test State Pattern - Selenium Camp 2017
Roi Ashkenazi
 
Grading the Quality of Selenium Tests
Grading the Quality of Selenium TestsGrading the Quality of Selenium Tests
Grading the Quality of Selenium Tests
Marcus Merrell
 
5 top pain points of test automation
5 top pain points of test automation5 top pain points of test automation
5 top pain points of test automation
Mikalai Alimenkou
 
Design patterns in test automation
Design patterns in test automationDesign patterns in test automation
Design patterns in test automation
Mikalai Alimenkou
 
Test trend analysis: Towards robust reliable and timely tests
Test trend analysis: Towards robust reliable and timely testsTest trend analysis: Towards robust reliable and timely tests
Test trend analysis: Towards robust reliable and timely tests
Hugh McCamphill
 
How does Java 8 exert hidden power on Test Automation?
How does Java 8 exert hidden power on Test Automation?How does Java 8 exert hidden power on Test Automation?
How does Java 8 exert hidden power on Test Automation?
Sergey Korol
 
Testing Metrics - Making your tests visible
Testing Metrics - Making your tests visibleTesting Metrics - Making your tests visible
Testing Metrics - Making your tests visible
Alper Mermer
 
Roman iovlev battle - JDI vs Selenide - Selenium Camp
Roman iovlev battle - JDI vs Selenide - Selenium CampRoman iovlev battle - JDI vs Selenide - Selenium Camp
Roman iovlev battle - JDI vs Selenide - Selenium Camp
РОПан ИОвНов
 
SoapUI one key to all doors
SoapUI one key to all doorsSoapUI one key to all doors
SoapUI one key to all doors
Yegor Maksymchuk
 
Colorful world-of-visual-automation-testing-latest
Colorful world-of-visual-automation-testing-latestColorful world-of-visual-automation-testing-latest
Colorful world-of-visual-automation-testing-latest
Onur Baskirt
 
Test Automation Architecture in Microservices
Test Automation Architecture in MicroservicesTest Automation Architecture in Microservices
Test Automation Architecture in Microservices
Alper Mermer
 
Selenide
SelenideSelenide
SelenideISsoft
 
Garbage collected teardown
Garbage collected teardownGarbage collected teardown
Garbage collected teardown
Hiroyuki Ohnaka
 
xUnit Test Patterns Chapter 20
xUnit Test Patterns Chapter 20xUnit Test Patterns Chapter 20
xUnit Test Patterns Chapter 20
Hiroyuki Ohnaka
 
Little productivity tools every developer should use
Little productivity tools every developer should useLittle productivity tools every developer should use
Little productivity tools every developer should use
Dennis Doomen
 
Automated Testing and Continuous Integration for Mobile Apps: Jenkins & Cloud...
Automated Testing and Continuous Integration for Mobile Apps: Jenkins & Cloud...Automated Testing and Continuous Integration for Mobile Apps: Jenkins & Cloud...
Automated Testing and Continuous Integration for Mobile Apps: Jenkins & Cloud...
SOASTA
 
DOES14 - Jonny Wooldridge - The Cambridge Satchel Company - 10 Enterprise Tip...
DOES14 - Jonny Wooldridge - The Cambridge Satchel Company - 10 Enterprise Tip...DOES14 - Jonny Wooldridge - The Cambridge Satchel Company - 10 Enterprise Tip...
DOES14 - Jonny Wooldridge - The Cambridge Satchel Company - 10 Enterprise Tip...
Gene Kim
 
Jvm-bdd-quality-driven
Jvm-bdd-quality-drivenJvm-bdd-quality-driven
Jvm-bdd-quality-driven
Amir Barylko
 
BDD for Rails Legacy Code
BDD for Rails Legacy CodeBDD for Rails Legacy Code
BDD for Rails Legacy Code
Wei Jen Lu
 

Viewers also liked (20)

Excuse me, sir, do you have a moment to talk about tests in Kotlin
Excuse me, sir, do you have a moment to talk about tests in KotlinExcuse me, sir, do you have a moment to talk about tests in Kotlin
Excuse me, sir, do you have a moment to talk about tests in Kotlin
 
WixAutomation - Test State Pattern - Selenium Camp 2017
WixAutomation - Test State Pattern - Selenium Camp 2017WixAutomation - Test State Pattern - Selenium Camp 2017
WixAutomation - Test State Pattern - Selenium Camp 2017
 
Grading the Quality of Selenium Tests
Grading the Quality of Selenium TestsGrading the Quality of Selenium Tests
Grading the Quality of Selenium Tests
 
5 top pain points of test automation
5 top pain points of test automation5 top pain points of test automation
5 top pain points of test automation
 
Design patterns in test automation
Design patterns in test automationDesign patterns in test automation
Design patterns in test automation
 
Test trend analysis: Towards robust reliable and timely tests
Test trend analysis: Towards robust reliable and timely testsTest trend analysis: Towards robust reliable and timely tests
Test trend analysis: Towards robust reliable and timely tests
 
How does Java 8 exert hidden power on Test Automation?
How does Java 8 exert hidden power on Test Automation?How does Java 8 exert hidden power on Test Automation?
How does Java 8 exert hidden power on Test Automation?
 
Testing Metrics - Making your tests visible
Testing Metrics - Making your tests visibleTesting Metrics - Making your tests visible
Testing Metrics - Making your tests visible
 
Roman iovlev battle - JDI vs Selenide - Selenium Camp
Roman iovlev battle - JDI vs Selenide - Selenium CampRoman iovlev battle - JDI vs Selenide - Selenium Camp
Roman iovlev battle - JDI vs Selenide - Selenium Camp
 
SoapUI one key to all doors
SoapUI one key to all doorsSoapUI one key to all doors
SoapUI one key to all doors
 
Colorful world-of-visual-automation-testing-latest
Colorful world-of-visual-automation-testing-latestColorful world-of-visual-automation-testing-latest
Colorful world-of-visual-automation-testing-latest
 
Test Automation Architecture in Microservices
Test Automation Architecture in MicroservicesTest Automation Architecture in Microservices
Test Automation Architecture in Microservices
 
Selenide
SelenideSelenide
Selenide
 
Garbage collected teardown
Garbage collected teardownGarbage collected teardown
Garbage collected teardown
 
xUnit Test Patterns Chapter 20
xUnit Test Patterns Chapter 20xUnit Test Patterns Chapter 20
xUnit Test Patterns Chapter 20
 
Little productivity tools every developer should use
Little productivity tools every developer should useLittle productivity tools every developer should use
Little productivity tools every developer should use
 
Automated Testing and Continuous Integration for Mobile Apps: Jenkins & Cloud...
Automated Testing and Continuous Integration for Mobile Apps: Jenkins & Cloud...Automated Testing and Continuous Integration for Mobile Apps: Jenkins & Cloud...
Automated Testing and Continuous Integration for Mobile Apps: Jenkins & Cloud...
 
DOES14 - Jonny Wooldridge - The Cambridge Satchel Company - 10 Enterprise Tip...
DOES14 - Jonny Wooldridge - The Cambridge Satchel Company - 10 Enterprise Tip...DOES14 - Jonny Wooldridge - The Cambridge Satchel Company - 10 Enterprise Tip...
DOES14 - Jonny Wooldridge - The Cambridge Satchel Company - 10 Enterprise Tip...
 
Jvm-bdd-quality-driven
Jvm-bdd-quality-drivenJvm-bdd-quality-driven
Jvm-bdd-quality-driven
 
BDD for Rails Legacy Code
BDD for Rails Legacy CodeBDD for Rails Legacy Code
BDD for Rails Legacy Code
 

Similar to Better Bullshit Driven Development [SeleniumCamp 2017]

Geb qa fest2017
Geb qa fest2017Geb qa fest2017
Geb qa fest2017
Sviatkin Yaroslav
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmers
Alexander Varwijk
 
Smarttuts Project ppt
Smarttuts Project pptSmarttuts Project ppt
Smarttuts Project ppt
Khushal Bhakre
 
Continuous integration using thucydides(bdd) with selenium
Continuous integration using thucydides(bdd) with seleniumContinuous integration using thucydides(bdd) with selenium
Continuous integration using thucydides(bdd) with selenium
Xebia IT Architects
 
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QAFest
 
CDI @javaonehyderabad
CDI @javaonehyderabadCDI @javaonehyderabad
CDI @javaonehyderabad
Prasad Subramanian
 
A test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobileA test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobile
GlobalLogic Ukraine
 
Continuous integration using thucydides(bdd) with selenium
Continuous integration using thucydides(bdd) with  seleniumContinuous integration using thucydides(bdd) with  selenium
Continuous integration using thucydides(bdd) with selenium
Khyati Sehgal
 
The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210
Mahmoud Samir Fayed
 
Code generation for alternative languages
Code generation for alternative languagesCode generation for alternative languages
Code generation for alternative languages
Rafael Winterhalter
 
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
NETFest
 
Html5 For Jjugccc2009fall
Html5 For Jjugccc2009fallHtml5 For Jjugccc2009fall
Html5 For Jjugccc2009fall
Shumpei Shiraishi
 
Android Studio Assignment HelpCan someone who is familiar with And.pdf
Android Studio Assignment HelpCan someone who is familiar with And.pdfAndroid Studio Assignment HelpCan someone who is familiar with And.pdf
Android Studio Assignment HelpCan someone who is familiar with And.pdf
feelinggift
 
Wicket In Action - oredev2008
Wicket In Action - oredev2008Wicket In Action - oredev2008
Wicket In Action - oredev2008
Martijn Dashorst
 
Teste de Integração com DbUnit e jIntegrity
Teste de Integração com DbUnit e jIntegrityTeste de Integração com DbUnit e jIntegrity
Teste de Integração com DbUnit e jIntegrity
Washington Botelho
 
Creating a Simple PHP and MySQL-Based Login System
Creating a Simple PHP and MySQL-Based Login SystemCreating a Simple PHP and MySQL-Based Login System
Creating a Simple PHP and MySQL-Based Login System
Azharul Haque Shohan
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
Hugo Hamon
 
#JavaFX.forReal()
#JavaFX.forReal()#JavaFX.forReal()
#JavaFX.forReal()
Thierry Wasylczenko
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
Max Claus Nunes
 
Tools and Projects Dec 2018 Edition
Tools and Projects Dec 2018 EditionTools and Projects Dec 2018 Edition
Tools and Projects Dec 2018 Edition
Jesus Manuel Olivas
 

Similar to Better Bullshit Driven Development [SeleniumCamp 2017] (20)

Geb qa fest2017
Geb qa fest2017Geb qa fest2017
Geb qa fest2017
 
Multilingualism makes better programmers
Multilingualism makes better programmersMultilingualism makes better programmers
Multilingualism makes better programmers
 
Smarttuts Project ppt
Smarttuts Project pptSmarttuts Project ppt
Smarttuts Project ppt
 
Continuous integration using thucydides(bdd) with selenium
Continuous integration using thucydides(bdd) with seleniumContinuous integration using thucydides(bdd) with selenium
Continuous integration using thucydides(bdd) with selenium
 
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
QA Fest 2017. Ярослав Святкин. Тестовый фреймворк GEB для тестирования WEB пр...
 
CDI @javaonehyderabad
CDI @javaonehyderabadCDI @javaonehyderabad
CDI @javaonehyderabad
 
A test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobileA test framework out of the box - Geb for Web and mobile
A test framework out of the box - Geb for Web and mobile
 
Continuous integration using thucydides(bdd) with selenium
Continuous integration using thucydides(bdd) with  seleniumContinuous integration using thucydides(bdd) with  selenium
Continuous integration using thucydides(bdd) with selenium
 
The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210The Ring programming language version 1.9 book - Part 54 of 210
The Ring programming language version 1.9 book - Part 54 of 210
 
Code generation for alternative languages
Code generation for alternative languagesCode generation for alternative languages
Code generation for alternative languages
 
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
.NET Fest 2017. Михаил Щербаков. Механизмы предотвращения атак в ASP.NET Core
 
Html5 For Jjugccc2009fall
Html5 For Jjugccc2009fallHtml5 For Jjugccc2009fall
Html5 For Jjugccc2009fall
 
Android Studio Assignment HelpCan someone who is familiar with And.pdf
Android Studio Assignment HelpCan someone who is familiar with And.pdfAndroid Studio Assignment HelpCan someone who is familiar with And.pdf
Android Studio Assignment HelpCan someone who is familiar with And.pdf
 
Wicket In Action - oredev2008
Wicket In Action - oredev2008Wicket In Action - oredev2008
Wicket In Action - oredev2008
 
Teste de Integração com DbUnit e jIntegrity
Teste de Integração com DbUnit e jIntegrityTeste de Integração com DbUnit e jIntegrity
Teste de Integração com DbUnit e jIntegrity
 
Creating a Simple PHP and MySQL-Based Login System
Creating a Simple PHP and MySQL-Based Login SystemCreating a Simple PHP and MySQL-Based Login System
Creating a Simple PHP and MySQL-Based Login System
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
 
#JavaFX.forReal()
#JavaFX.forReal()#JavaFX.forReal()
#JavaFX.forReal()
 
Flask – Python
Flask – PythonFlask – Python
Flask – Python
 
Tools and Projects Dec 2018 Edition
Tools and Projects Dec 2018 EditionTools and Projects Dec 2018 Edition
Tools and Projects Dec 2018 Edition
 

Recently uploaded

Operating System Used by Users in day-to-day life.pptx
Operating System Used by Users in day-to-day life.pptxOperating System Used by Users in day-to-day life.pptx
Operating System Used by Users in day-to-day life.pptx
Pravash Chandra Das
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
Tomaz Bratanic
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
Jason Packer
 
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Jeffrey Haguewood
 
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - HiikeSystem Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
Hiike
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
Chart Kalyan
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
Zilliz
 
dbms calicut university B. sc Cs 4th sem.pdf
dbms  calicut university B. sc Cs 4th sem.pdfdbms  calicut university B. sc Cs 4th sem.pdf
dbms calicut university B. sc Cs 4th sem.pdf
Shinana2
 
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdfMonitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Tosin Akinosho
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
Jakub Marek
 
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStrDeep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
saastr
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
MichaelKnudsen27
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
akankshawande
 
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Tatiana Kojar
 
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
Jeffrey Haguewood
 
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying AheadDigital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Wask
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
Zilliz
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Alpen-Adria-Universität
 

Recently uploaded (20)

Operating System Used by Users in day-to-day life.pptx
Operating System Used by Users in day-to-day life.pptxOperating System Used by Users in day-to-day life.pptx
Operating System Used by Users in day-to-day life.pptx
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
 
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
 
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - HiikeSystem Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
 
Programming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup SlidesProgramming Foundation Models with DSPy - Meetup Slides
Programming Foundation Models with DSPy - Meetup Slides
 
dbms calicut university B. sc Cs 4th sem.pdf
dbms  calicut university B. sc Cs 4th sem.pdfdbms  calicut university B. sc Cs 4th sem.pdf
dbms calicut university B. sc Cs 4th sem.pdf
 
Monitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdfMonitoring and Managing Anomaly Detection on OpenShift.pdf
Monitoring and Managing Anomaly Detection on OpenShift.pdf
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
 
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStrDeep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
 
TrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy SurveyTrustArc Webinar - 2024 Global Privacy Survey
TrustArc Webinar - 2024 Global Privacy Survey
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
 
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
Skybuffer AI: Advanced Conversational and Generative AI Solution on SAP Busin...
 
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
Letter and Document Automation for Bonterra Impact Management (fka Social Sol...
 
Digital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying AheadDigital Marketing Trends in 2024 | Guide for Staying Ahead
Digital Marketing Trends in 2024 | Guide for Staying Ahead
 
Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
 

Better Bullshit Driven Development [SeleniumCamp 2017]

  • 3. @juliaviluhina @yashaka Better Bullshit Driver Development Preface
  • 4. Plan Preface: Classic BDD & xUnit examples BDD Intro Better BDD with xUnit + Allure Q&A
  • 6. xUnit style public class DiasporaTest extends BaseTest {
 LoginPage loginPage = new LoginPage();
 NewPost newPost = new NewPost();
 Stream stream = new Stream();
 
 @Test
 public void shareMessage() {
 loginPage.open();
 loginPage.signIn(Users.Selenide.username, Users.Selenide.password);
 newPost.start();
 newPost.write("Selenide 4.2 released!");
 newPost.share();
 stream.shouldHavePostWithText(0, "Selenide 4.2 released!");
 }
 }
  • 7. xUnit style public class DiasporaTest extends BaseTest {
 LoginPage loginPage = new LoginPage();
 NewPost newPost = new NewPost();
 Stream stream = new Stream();
 
 @Test
 public void shareMessage() {
 loginPage.open();
 loginPage.signIn(Users.Selenide.username, Users.Selenide.password);
 newPost.start();
 newPost.write("Selenide 4.2 released!");
 newPost.share();
 stream.shouldHavePostWithText(0, "Selenide 4.2 released!");
 }
 }
  • 8. BDD style (option 1) @defaults
 Feature: Diaspora
 
 Scenario: Share message
 Given I open login page
 And I do sign in with credentials: 'selenide', 'xxxxxxxx'
 When I start new post
 And write new post message: 'Selenide 4.2 is released!'
 And share new post
 Then stream should have post with index '1' of text 'Selenide 4.2 is released!'
  • 9. BDD style (option 1) public class DiasporaStepdefs {
 LoginPage loginPage = new LoginPage();
 NewPost newPost = new NewPost();
 Stream stream = new Stream();
 
 @Given("^I open login page$")
 public void I_open_login_page(){
 loginPage.open();
 }
 
 
 @And("^I do sign in with credentials: '(.+)', '(.+)'$")
 public void I_do_sign_in_with_credentials_selenide_yagniyagni(String username, String password) {
 loginPage.signIn(username, password);
 } ...
  • 10. BDD style (option 1) ...
 @When("^I start new post$")
 public void I_start_new_post(){
 newPost.start();
 }
 
 @And("^write new post message: '(.+)'$")
 public void write_new_post_message_Selenide_is_released_(String text){
 newPost.write(text);
 } ...
  • 11. BDD style (option 1) ... @And("^share new post$")
 public void share_new_post() {
 newPost.share();
 }
 
 @Then("^stream should have post with index '( d+)' of text '(.+)'$")
 public void stream_should_have_post_with_index_of_text_Selenide_is_released_(int index, String text) {
 stream.shouldHavePostWithText(index-1, text);
 }
 }
  • 12.
  • 13. BDD style (option 2) @defaults
 Feature: Diaspora
 
 Scenario: Share message
 Given I signed in from login page with credentials: 'selenide', 'xxxx'
 When I publish new post: 'Selenide 4.2 is released!'
 Then I should see new post 'Selenide 4.2 is released!' in the top of stream
  • 14. BDD style (option 2) public class DiasporaStepdefs {
 LoginPage loginPage = new LoginPage();
 NewPost newPost = new NewPost();
 Stream stream = new Stream();
 
 @Given("^I signed in from login page with credentials: '(.+)', '(.+)'$")
 public void I_signed_in_from_login_page_with_credentials_selenide_yagniyagni(String username, String password) {
 loginPage.open();
 loginPage.signIn(username, password);
 } ...
  • 15. BDD style (option 2) ... @When("^I publish new post: '(.+)'$")
 public void I_publish_new_post_Selenide_is_released_(String text) {
 newPost.start();
 newPost.write(text);
 newPost.share();
 }
 
 @Then("^I should see new post '(.+)' in the top of stream$")
 public void I_should_see_new_post_Selenide_is_released_in_the_top_of_stream(String text) {
 stream.shouldHavePostWithText(0, text);
 }
 }
  • 16.
  • 23. =BDD Optimised ATDD giving as a bonus: readable scenarios and reports
  • 25. = Optimised ATDD = Devs write tests rst BDD
  • 26. = Optimised ATDD = Devs write acceptance tests rst BDD
  • 27. = Optimised ATDD = Devs write acceptance tests rst based on scenarios already written by BA/PO BDD
  • 28. = Optimised ATDD = Devs write acceptance tests rst based on scenarios already written by BA/PO BDD
  • 29. =BDD Optimised ATDD = Devs write acceptance tests rst based on scenarios already written by BA/PO unbiased thinking of end product doing things once (reqs are 2 in 1 - are already automatable)
  • 30. =BDD Optimised ATDD = Devs write acceptance tests rst based on scenarios already written by BA/PO unbiased thinking of end product doing things once (reqs are 2 in 1 - are already automatable)
  • 31. Optimised ATDD = Devs write acceptance tests rst based on scenarios already written by BA/PO unbiased thinking of end product doing things once (reqs are 2 in 1 - are already automatable) Behaviour Driven Development
  • 32. Optimised ATDD = Devs write acceptance tests rst based on scenarios already written by BA/PO unbiased thinking of end product doing things once (reqs are 2 in 1 - are already automatable) Beh?viour Driven Development
  • 33. Optimised ATDD = Devs write acceptance tests rst based on scenarios already written by BA/PO Automation engineers write tests after. adding extra “readable scenarios” layer for “good reports” Beh?viour Driven Development vs vs
  • 34. Optimised ATDD = Devs write acceptance tests rst based on scenarios already written by BA/PO Automation engineers write tests after. adding extra “readable scenarios” layer for “good reports” Bullshit Driven Development vs vs
  • 35. WTF? adding additional limited pseudo-programming layer just to make tests readable and with good reports?
  • 36. WTF? adding additional limited pseudo-programming layer just to make tests readable and with good reports?
  • 37. Better “Bullshit” Driven Development without additional limited pseudo programming layers ;)
  • 39. pom.xml with just xUnit + Selenide <dependencies>
 <dependency>
 <groupId>com.codeborne </groupId>
 <artifactId>selenide </artifactId>
 <version>4.2 </version>
 <scope>test </scope>
 </dependency>
 <dependency>
 <groupId>junit </groupId>
 <artifactId>junit </artifactId>
 <version>4.12 </version>
 </dependency>
 </dependencies>
  • 40. xUnit + PageObject with readable steps public class DiasporaTest extends BaseTest {
 LoginPage loginPage = new LoginPage();
 NewPost newPost = new NewPost();
 Stream stream = new Stream();
 
 @Test
 public void shareMessage() {
 loginPage.open();
 loginPage.signIn(Users.Selenide.username, Users.Selenide.password);
 newPost.start();
 newPost.write("Selenide 4.2 released!");
 newPost.share();
 stream.shouldHavePostWithText(0, "Selenide 4.2 released!");
 }
 }
  • 41. xUnit + PageObject with readable steps public class DiasporaTest extends BaseTest {
 LoginPage loginPage = new LoginPage();
 NewPost newPost = new NewPost();
 Stream stream = new Stream();
 
 @Test
 public void shareMessage() {
 loginPage.open();
 loginPage.signIn(Users.Selenide.username, Users.Selenide.password);
 newPost.start();
 newPost.write("Selenide 4.2 released!");
 newPost.share();
 stream.shouldHavePostWithText(0, "Selenide 4.2 released!");
 }
 }
  • 42. xUnit + PageObject with readable steps public class DiasporaTest extends BaseTest {
 LoginPage loginPage = new LoginPage();
 NewPost newPost = new NewPost();
 Stream stream = new Stream();
 
 @Test
 public void shareMessage() {
 loginPage.open();
 loginPage.signIn(Users.Selenide.username, Users.Selenide.password);
 newPost.start();
 newPost.write("Selenide 4.2 released!");
 newPost.share();
 stream.shouldHavePostWithText(0, "Selenide 4.2 released!");
 }
 }
  • 43. xUnit + PageObject with readable steps public class LoginPage {
 
 public void open() {
 Selenide.open("/users/sign_in");
 }
 
 public void signIn(String username, String password) {
 Form form = new Form($("#new_user"));
 form.set("USERNAME", username);
 form.set("PASSWORD", password);
 form.submit();
 }
 }
  • 44. xUnit + PageObject with readable steps Report :(
  • 45. Better xUnit reports with Allure
  • 47. <build>
 <plugins>
 <plugin>
 <groupId>org.apache.maven.plugins </groupId>
 <artifactId>maven-surefire-plugin </artifactId>
 <version>2.19.1 </version>
 <configuration>
 <testFailureIgnore>false </testFailureIgnore>
 <argLine>
 -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
 </argLine>
 <properties>
 <property>
 <name>listener </name>
 <value>ru.yandex.qatools.allure.junit.AllureRunListener </value>
 </property>
 </properties>
 </configuration>
 <dependencies>
 <dependency>
 <groupId>org.aspectj </groupId>
 <artifactId>aspectjweaver </artifactId>
 <version>${aspectj.version} </version>
 </dependency>
 </dependencies>
 </plugin>
 ...
 </plugins>
 </build>
  • 50. xUnit + PageObject with reportable @Steps :) public class DiasporaTest extends BaseTest {
 LoginPage loginPage = new LoginPage();
 NewPost newPost = new NewPost();
 Stream stream = new Stream();
 
 @Test
 public void shareMessage() {
 loginPage.open();
 loginPage.signIn(Users.Selenide.username, Users.Selenide.password);
 newPost.start();
 newPost.write("Selenide 4.2 released!");
 newPost.share();
 stream.shouldHavePostWithText(0, "Selenide 4.2 released!");
 }
 }
  • 51. xUnit + PageObject with reportable @Steps :) public class LoginPage {
 
 @Step
 public void open() {
 Selenide.open("/users/sign_in");
 }
 
 @Step
 public void signIn(String username, String password) {
 Form form = new Form($("#new_user"));
 form.set("USERNAME", username);
 form.set("PASSWORD", password);
 form.submit();
 }
 }
  • 52. xUnit + PageObject with reportable @Steps :) Report
  • 53. xUnit + PageObject with reportable @Steps :) Report
  • 54. xUnit + PageObject with reportable @Steps :) Report qwerty1234
  • 55. xUnit + PageObject with reportable @Steps :) Report qwerty1234 qwerty1234
  • 56. Missed “objects info” in reports :( public class DiasporaTest extends BaseTest {
 LoginPage loginPage = new LoginPage();
 NewPost newPost = new NewPost();
 Stream stream = new Stream();
 
 @Test
 public void shareMessage() {
 loginPage.open();
 loginPage.signIn(Users.Selenide.username, Users.Selenide.password);
 newPost.start();
 newPost.write("Selenide 4.2 released!");
 newPost.share();
 stream.shouldHavePostWithText(0, "Selenide 4.2 released!");
 }
 }
  • 57. Report :( Missed “objects info” in reports :( What is opened? Where do we do signin? What do we start? Where?
  • 58. Fixing “missed objects” with One Entry Point to PageObjects :) public class DiasporaTest extends BaseTest {
 Diaspora diaspora = new Diaspora();
 
 @Test
 public void shareMessage() {
 diaspora.loginPage().open();
 diaspora.loginPage()
 .signIn(Users.Selenide.username, Users.Selenide.password);
 diaspora.newPost().start();
 diaspora.newPost().write("Selenide 4.2 released!");
 diaspora.newPost().share();
 diaspora.stream().shouldHavePostWithText(0, "Selenide 4.2 released!");
 }
 }
  • 59. Fixing “missed objects” with One Entry Point to PageObjects :) public class Diaspora {
 
 @Step
 public LoginPage loginPage() {
 return new LoginPage();
 }
 
 @Step
 public NewPost newPost() {
 return new NewPost();
 }
 
 @Step
 public Stream stream() {
 return new Stream();
 } ...
 }
  • 60. Fixing “missed objects” with One Entry Point to PageObjects :) public class Diaspora {
 
 @Step
 public LoginPage loginPage() {
 return new LoginPage();
 }
 
 @Step
 public NewPost newPost() {
 return new NewPost();
 }
 
 @Step
 public Stream stream() {
 return new Stream();
 } ...
 } The simplest impl. with redundant objects, not actually influencing performance much
  • 61. Fixing “missed objects” with One Entry Point to PageObjects :) public class Diaspora {
 private final LoginPage loginPage;
 private final NewPost newPost;
 private final Stream stream;
 
 public Diaspora() {
 this.loginPage = new LoginPage();
 this.newPost = new NewPost();
 this.stream = new Stream();
 }
 
 @Step
 public LoginPage loginPage() {
 return this.loginPage;
 }
 ...
 } but in case you bother…
  • 62. Fixing “missed objects” with One Entry Point to PageObjects :) public class Application {
 private final LoginPage loginPage;
 private final NewPost newPost;
 private final Stream stream;
 
 public Application() {
 this.loginPage = new LoginPage();
 this.newPost = new NewPost();
 this.stream = new Stream();
 }
 
 @Step
 public LoginPage loginPage() {
 return this.loginPage;
 }
 ...
 } aka Application Manager
  • 63. Fixing “missed objects” with One Entry Point to PageObjects :) public class DiasporaTest extends BaseTest {
 Application app = new Application();
 
 @Test
 public void shareMessage() {
 app.loginPage().open();
 app.loginPage()
 .signIn(Users.Selenide.username, Users.Selenide.password);
 app.newPost().start();
 app.newPost().write("Selenide 4.2 released!");
 app.newPost().share();
 app.stream().shouldHavePostWithText(0, "Selenide 4.2 released!");
 }
 } aka Application Manager
  • 64. Fixing “missed objects” with One Entry Point to PageObjects :) Report
  • 65. Fixing “missed objects” with One Entry Point to PageObjects :) Report May be a bit “too long” while reading to nd “logical code sentences”…
  • 66. Fixing “missed objects” with One Entry Point to PageObjects :) Report But if consider that “each sentence” is two lines it becomes to make sense:)
  • 67. Applying Fluent PageObject for easier scenarios … public class DiasporaTest extends BaseTest {
 Diaspora diaspora = new Diaspora();
 
 @Test
 public void shareMessage() {
 diaspora.loginPage().open().signIn(
 Users.Selenide.username,
 Users.Selenide.password);
 diaspora.newPost().start().write("Selenide 4.2 released!").share();
 diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");
 }
 }
  • 68. Applying Fluent PageObject for easier scenarios … public class DiasporaTest extends BaseTest {
 Diaspora diaspora = new Diaspora();
 
 @Test
 public void shareMessage() {
 diaspora.loginPage().open().signIn(
 Users.Selenide.username,
 Users.Selenide.password);
 diaspora.newPost().start().write("Selenide 4.2 released!").share();
 diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");
 }
 }
  • 69. Applying Fluent PageObject for easier scenarios … public class DiasporaTest extends BaseTest {
 Diaspora diaspora = new Diaspora();
 
 @Test
 public void shareMessage() {
 diaspora.loginPage().open().signIn(
 Users.Selenide.username,
 Users.Selenide.password);
 diaspora.newPost().start().write("Selenide 4.2 released!").share();
 diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");
 }
 }
  • 70. Applying Fluent PageObject for easier scenarios … public class NewPost {
 ...
 @Step
 public NewPost start() {
 this.textArea.click();
 return this;
 }
 
 @Step
 public NewPost write(String text) {
 this.textArea.setValue(text);
 return this;
 }
 
 @Step
 public void share(){
 this.container.find("#submit").click();
 }

  • 71. Applying Fluent PageObject for easier scenarios … public class NewPost {
 ...
 @Step
 public NewPost start() {
 this.textArea.click();
 return this;
 }
 
 @Step
 public NewPost write(String text) {
 this.textArea.setValue(text);
 return this;
 }
 
 @Step
 public void share(){
 this.container.find("#submit").click();
 }
 no need to be “fluent” here, as we do not know, where user should proceed a flow
  • 72. … may lead to “missing flow” in reports :( Report :( Where does the sentence start and nish?
  • 73. … may lead to “missing flow” in reports :( Report :( Where does the sentence start and nish?
  • 74. Fixing “missed flow” with “gherkin” pseudo-steps… public class DiasporaTest extends BaseTest {
 Diaspora diaspora = new Diaspora();
 
 @Test
 public void shareMessage() {
 GIVEN("Logged in from login page");
 diaspora.loginPage().open().signIn(
 Users.Selenide.username,
 Users.Selenide.password);
 WHEN("Posted new message");
 diaspora.newPost().start().write("Selenide 4.2 released!").share();
 THEN("Message should appear in the stream");
 diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");
 }
 }
  • 75. Fixing “missed flow” with “gherkin” pseudo-steps… public class Gherkin {
 
 @Step
 public static void GIVEN(String step) {}
 
 @Step
 public static void AND(String step) {}
 
 @Step
 public static void WHEN(String step) {}
 
 @Step
 public static void THEN(String step) {}
 }
  • 76. Fixing “missed flow” with “gherkin” pseudo-steps… Report :)
  • 77. Fixing “missed flow” with “gherkin” pseudo-steps… Report :) Each new “code sentence” starts with a “gherkin” keyword
  • 78. Fixing “missed flow” with “gherkin” pseudo-steps… Report (more complicated example)
  • 79. Fixing “missed flow” with “gherkin” pseudo-steps… Report (more complicated example)
  • 80. Illustration (more complicated example) Fixing “missed flow” with “gherkin” pseudo-steps…
  • 81. … leads sometimes to even more to readable code THEN("Connect first cell of this column to first row from data storage");
 app.testTable().row(0).cell(0).fill("1").hover();
 
 EXPECT("Connection works by showing connected data in a cell tooltip (on hover)");
 app.testTable().toolTip()
 .shouldHaveKeyRowCells("", "user", "password")
 .shouldHaveValueRowCells("1", "vasya", "pupkin1234"); Implementation (more complicated example)
  • 82. … leads sometimes to not much more readable public class DiasporaTest extends BaseTest {
 Diaspora diaspora = new Diaspora();
 
 @Test
 public void shareMessage() {
 GIVEN("Logged in from login page");
 diaspora.loginPage().open().signIn(
 Users.Selenide.username,
 Users.Selenide.password);
 WHEN("Posted new message");
 diaspora.newPost().start().write("Selenide 4.2 released!").share();
 THEN("Message should appear in the stream");
 diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");
 }
 }
  • 83. … and often redundant code :| public class DiasporaTest extends BaseTest {
 Diaspora diaspora = new Diaspora();
 
 @Test
 public void shareMessage() {
 GIVEN("Logged in from login page");
 diaspora.loginPage().open().signIn(
 Users.Selenide.username,
 Users.Selenide.password);
 WHEN("Posted new message");
 diaspora.newPost().start().write("Selenide 4.2 released!").share();
 THEN("Message should appear in the stream");
 diaspora.stream().post(0).shouldBe("Selenide 4.2 released!");
 }
 } just repeats already readable “code”
  • 84. Fixing everything:) with “gherkin” style of One Entry Point public class DiasporaTest extends GherkinTest {
 
 @Test
 public void shareMessage() {
 GIVEN().loginPage().open().signIn(
 Users.Selenide.username,
 Users.Selenide.password);
 WHEN().newPost().start().write("Selenide 4.2 released!").share();
 THEN().stream().post(0).shouldBe("Selenide 4.2 released!");
 }
 }
  • 85. Fixing everything:) with “gherkin” style of One Entry Point public class GherkinTest {
 ...
 Diaspora diaspora = new Diaspora();
 
 @Step
 public Diaspora GIVEN(String ... comments) { return this.diaspora; }
 
 @Step
 public Diaspora AND(String ... comments) { return this.diaspora; }
 
 @Step
 public Diaspora WHEN(String ... comments) { return this.diaspora; }
 
 @Step
 public Diaspora THEN(String ... comments) { return this.diaspora; }
 }
  • 86. Fixing everything:) with “gherkin” style of One Entry Point Report :D Each new “code sentence” starts with a “gherkin” keyword
  • 87. Fixing everything:) with “gherkin” style of One Entry Point THEN("Connect first cell of this column to first row from data storage")
 .testTable().row(0).cell(0).fill("1").hover();
 
 EXPECT("Connection works by showing connected data in a cell tooltip (on hover)")
 .testTable().toolTip()
 .shouldHaveKeyRowCells("", "user", "password")
 .shouldHaveValueRowCells("1", "vasya", "pupkin1234"); Implementation (more complicated example) with additional step comments when needed
  • 88. Fixing everything:) with “gherkin” style of One Entry Point Report (more complicated example)
  • 89. Summary GIVEN no BA writing Gherkin AND automation engineers writing tests after WHEN xUnit AND Fluent PageObjects with Allure readable @Steps AND Gherkin style of One Entry Point (aka Application Manager) THEN Bullshit Driven Development is Better
  • 90. Better Bullshit Driven Development with xUnit, Fluent PageObjects, Allure @Steps, “Gherkined" One Entry Point • all-powerful programming language over textual-pseudo-language • full IDE support (autocompletion, auto-generate, etc.) • 1 abstraction layer less => simpler and faster in implementation • still fully readable and with pretty good reports • newcomers friendly • Just One Entry Point to all Application Model • structured with granular Fluent PageObjects => easier to learn&use via autocompletion
  • 91. Better Bullshit Driven Development with xUnit, Fluent PageObjects, Allure @Steps, “Gherkined" One Entry Point • all-powerful programming language over textual-pseudo-language • full IDE support (autocompletion, auto-generate, etc.) • 1 abstraction layer less => simpler and faster in implementation • still fully readable and with pretty good reports • newcomers friendly • Just One Entry Point to all Application Model • structured with granular Fluent PageObjects => easier to learn&use via autocompletion
  • 92. Better Bullshit Driven Development with xUnit, Fluent PageObjects, Allure @Steps, “Gherkined" One Entry Point • all-powerful programming language over textual-pseudo-language • full IDE support (autocompletion, auto-generate, etc.) • 1 abstraction layer less => simpler and faster in implementation • still fully readable and with pretty good reports • newcomers friendly • Just One Entry Point to all Application Model • structured with granular Fluent PageObjects => easier to learn&use via autocompletion
  • 93. Better Bullshit Driven Development with xUnit, Fluent PageObjects, Allure @Steps, “Gherkined" One Entry Point • all-powerful programming language over textual-pseudo-language • full IDE support (autocompletion, auto-generate, etc.) • 1 abstraction layer less => simpler and faster in implementation • still fully readable and with pretty good reports • newcomers friendly • Just One Entry Point to all Application Model • structured with granular Fluent PageObjects => easier to learn&use via autocompletion
  • 94. Better Bullshit Driven Development with xUnit, Fluent PageObjects, Allure @Steps, “Gherkined" One Entry Point • all-powerful programming language over textual-pseudo-language • full IDE support (autocompletion, auto-generate, etc.) • 1 abstraction layer less => simpler and faster in implementation • still fully readable and with pretty good reports • newcomers friendly • Just One Entry Point to all Application Model • structured with granular Fluent PageObjects => easier to learn&use via autocompletion
  • 95. Better Bullshit Driven Development ;) public class DiasporaTest extends GherkinTest {
 
 @Test
 public void shareMessage() {
 GIVEN().loginPage().open().signIn(
 Users.Selenide.username,
 Users.Selenide.password);
 WHEN().newPost().start().write("Selenide 4.2 released!").share();
 THEN().stream().post(0).shouldBe("Selenide 4.2 released!");
 }
 }
  • 96. Better Bullshit Driven Development ;)
  • 97. More ideas • tune Allure to report objects (via calling their toString() method) • already possible? • contribute? • new Allure Feature: log object classes • contribute?
  • 98. Afterwords There are good practices in context, but there are no best practices. (c) Cem Kaner, James Bach
  • 99. Q&A
  • 101. You are welcome;) Selene in Python NSelene in C# Selenide snippets in Java Yashaka talks src code Selenide User Guide @juliaviluhina @yashaka