64
Completing the circle Automated web tests as a team communication tool John Ferguson Smart

Completing the circle - Automated web tests as a team communication tool

Embed Size (px)

Citation preview

Completing the circleAutomated web tests as a team communication tool

John Ferguson Smart

So who is this guy, anyway?

John Ferguson Smart

ConsultantTrainerMentorAuthorSpeakerCoder

The story of your app

ATDDor Specification by example

As a job seekerI want to find jobs in relevant categoriesSo that I can find a suitable job

User stories

Features/Epics

As a job seekerI want to find jobs in relevant categoriesSo that I can find a suitable job

User stories

☑  The  job  seeker  can  see  available  categories  on  the  home  page☑  The  job  seeker  can  look  for  jobs  in  a  given  category☑  The  job  seeker  can  see  what  category  a  job  belongs  to

Acceptance criteria

As a job seekerI want to find jobs in relevant categoriesSo that I can find a suitable job

User stories

☑  The  job  seeker  can  see  available  categories  on  the  home  page☑  The  job  seeker  can  look  for  jobs  in  a  given  category☑  The  job  seeker  can  see  what  category  a  job  belongs  to

scenario "A job seeker can see the available job categories on the home page",{ when "the job seeker is looking for a job", then "the job seeker can see all the available job categories"}

Automated acceptance test

Acceptance criteria

scenario "A job seeker can see the available job categories on the home page",{ when "the job seeker is looking for a job", then "the job seeker can see all the available job categories"}

Implemented development tests Implemented acceptance tests

Automated acceptance test

Technical tests are for the dev team

Not All Web Tests are Acceptance Tests

Acceptance tests are for everyone else

Technical tests talk to the dev team

Acceptance tests talk to everyone else

Not All Web Tests are Acceptance Tests

or how not to have web tests like this

The art of sustainable web tests

So what are our goals?

speak everybody’s language

Good web tests should

hide unnecessary details

Good web tests should

use reusable components

Good web tests should

be low maintenance

Good web tests should

The Three Ways of Automated Web Testing

Record/Replay

Scripting

Page Objects

Record-replay automated tests

Promise Reality

Record-replay automated tests

Script-based automated tests

Selenium RC

HTMLUnit

Canoe Webtest

JWebUnit

Watir

Script-based automated tests

Selenium RC

HTMLUnit

Canoe Webtest

JWebUnit

Watir

How about Page Objects?

Hide unnecessary detail

Reusable

Low maintenance

2

A sample Page ObjectA web page

A sample Page Object

lookForJobsWithKeywords(values : String)getJobTitles() : List<String>

FindAJobPage

A Page Object

A sample Page Object

public class FindAJobPage extends PageObject {

WebElement keywords; WebElement searchButton;

public FindAJobPage(WebDriver driver) { super(driver); }

public void lookForJobsWithKeywords(String values) { typeInto(keywords, values); searchButton.click(); }

public List<String> getJobTitles() { List<WebElement> tabs = getDriver() .findElements(By.xpath("//div[@id='jobs']//a")); return extract(tabs, on(WebElement.class).getText()); }}

An implemented Page Object

A sample Page Object

public class WhenSearchingForAJob {

@Test public void searching_for_a_job_should_display_matching_jobs() { FindAJobPage page = new FindAJobPage(); page.open("http://localhost:9000"); page.lookForJobsWithKeywords("Java"); assertThat(page.getJobTitles(), hasItem("Java Developer")); }}

A test using this Page Object

Sustainable web tests

Are we there yet?

The high-level view

Acceptance Tests

So  where  are  we  at?

Page Objects

Implementation focus

Page  Objects  rock!

How do we bridge the gap?

How do we bridge the gap?

Test steps

scenario "A job seeker can see the available job categories on the home page",{ when "the job seeker is looking for a job", then "the job seeker can see all the available job categories"}

Automated

scenario "The user can see the available job categories on the home page",{ when "the job seeker is looking for a job", { job_seeker.open_jobs_page() } then "the job seeker can see all the available job categories", { job_seeker.should_see_job_categories "Java Developers", "Groovy Developers" }}

Implemented

JobSeekerSteps

open_jobs_page()should_see_job_categories(String...  categories)...

JobSeekerSteps

open_jobs_page()should_see_job_categories(String...  categories)...

JobSeekerSteps

open_jobs_page()should_see_job_categories(String...  categories)...

Step libraries

scenario "The user can see the available job categories on the home page",{ when "the job seeker is looking for a job", { job_seeker.open_jobs_page() } then "the job seeker can see all the available job categories", { job_seeker.should_see_job_categories "Java Developers", "Groovy Developers" }}

JobSeekerSteps

open_jobs_page()should_see_job_categories(String...  categories)...

JobSeekerSteps

open_jobs_page()should_see_job_categories(String...  categories)...

JobSeekerSteps

open_jobs_page()should_see_job_categories(String...  categories)...

Step libraries

Page Objects

Implemented Tests

help organize your tests

Test steps

are a communication tool

Test steps

are reusable building blocks

Test steps

Test steps

help estimate progress

And so we built a tool...

Webdriver/Selenium 2 extension

Organize tests, stories and features

Measure functional coverage

Record/report test execution

Thucydides in action A simple demo app

Defining your acceptance tests

scenario "The administrator deletes a category from the system",{ given "a category needs to be deleted", when "the administrator deletes a category", then "the system will confirm that the category has been deleted", and "the deleted category should no longer be visible to job seekers",}

focus on business value

scenario "The administrator adds a new category to the system",{ given "a new category needs to be added to the system", when "the administrator adds a new category", then "the system should confirm that the category has been created", and "the new category should be visible to job seekers",}

...defined in business terms

scenario "A job seeker can see the available job categories on the home page",

{ when "the job seeker is looking for a job", then "the job seeker can see all the available job categories"}

High level requirements...

Organizing your requirements

public class Application {

@Feature public class ManageCompanies { public class AddNewCompany {} public class DeleteCompany {} public class ListCompanies {} }

@Feature public class ManageCategories { public class AddNewCategory {} public class ListCategories {} public class DeleteCategory {} }

@Feature public class BrowseJobs { public class UserLookForJobs {} public class UserBrowsesJobTabs {} }}

Features

Stories

Implementing your acceptance testsusing "thucydides"thucydides.uses_steps_from AdministratorStepsthucydides.uses_steps_from JobSeekerStepsthucydides.tests_story AddNewCategory

scenario "The administrator adds a new category to the system",{ given "a new category needs to be added to the system", { administrator.logs_in_to_admin_page_if_first_time() administrator.opens_categories_list() } when "the administrator adds a new category", { administrator.selects_add_category() administrator.adds_new_category("Scala Developers","SCALA") } then "the system should confirm that the category has been created", { administrator.should_see_confirmation_message "The Category has been created" } and "the new category should be visible to job seekers", { job_seeker.opens_jobs_page() job_seeker.should_see_job_category "Scala Developers" }}

We are testing this story

Narrative style

Step through an example

An acceptance criteria

Still high-level

Some folks prefer JUnit...@RunWith(ThucydidesRunner.class)@Story(AddNewCategory.class)public class AddCategoryStory {

@Managed public WebDriver webdriver;

@ManagedPages(defaultUrl = "http://localhost:9000") public Pages pages;

@Steps public AdministratorSteps administrator;

@Steps public JobSeekerSteps job_seeker;

@Test public void administrator_adds_a_new_category_to_the_system() { administrator.logs_in_to_admin_page_if_first_time(); administrator.opens_categories_list(); administrator.selects_add_category(); administrator.adds_new_category("Java Developers","JAVA"); administrator.should_see_confirmation_message("The Category has been created");

job_seeker.opens_job_page(); job_seeker.should_see_job_category("Java Developers"); }

@Pending @Test public void administrator_adds_an_existing_category_to_the_system() {}}

Thucydides handles the web driver instances

Using the same steps

Tests can be pending

Defining your test stepspublic class AdministratorSteps extends ScenarioSteps {

@Step public void opens_categories_list() { AdminHomePage page = getPages().get(AdminHomePage.class); page.open(); page.selectObjectType("Categories"); }

@Step public void selects_add_category() { CategoriesPage categoriesPage = getPages().get(CategoriesPage.class); categoriesPage.selectAddCategory(); }

@Step public void adds_new_category(String label, String code) { EditCategoryPage newCategoryPage = getPages().get(EditCategoryPage.class); newCategoryPage.saveNewCategory(label, code); }

@Step public void should_see_confirmation_message(String message) { AdminPage page = getPages().get(AdminPage.class); page.shouldContainConfirmationMessage(message); }

@StepGroup public void deletes_category(String name) { opens_categories_list(); displays_category_details_for(name); deletes_category(); }}

A step library

High level steps...

...implemented with Page Objects

...or with other steps

Defining your page objectspublic class EditCategoryPage extends PageObject {

@FindBy(id="object_label") WebElement label;

@FindBy(id="object_code") WebElement code;

@FindBy(name="_save") WebElement saveButton;

public EditCategoryPage(WebDriver driver) { super(driver); }

public void saveNewCategory(String labelValue, String codeValue) { typeInto(label, labelValue); typeInto(code, codeValue); saveButton.click(); }}

Provides some useful utility methods...

but otherwise a normal WebDriver Page Object

Data-driven testing

categories.csv

public class DataDrivenCategorySteps extends ScenarioSteps { public DataDrivenCategorySteps(Pages pages) { super(pages); }

private String name; private String code;

@Steps public AdminSteps adminSteps;

public void setCode(String code) {...} public void setName(String name) {...}

@Step public void add_a_category() { adminSteps.add_category(name, code); }}

Test data

Test steps

Data-driven testing

categories.csv

public class DataDrivenCategorySteps extends ScenarioSteps { public DataDrivenCategorySteps(Pages pages) { super(pages); }

private String name; private String code;

@Steps public AdminSteps adminSteps;

public void setCode(String code) {...} public void setName(String name) {...}

@Step public void add_a_category() { adminSteps.add_category(name, code); }}

@Steps public DataDrivenCategorySteps categorySteps;

@Test public void adding_multiple_categories() throws IOException { steps.login_to_admin_page_if_first_time(); steps.open_categories_list();

withTestDataFrom("categories.csv").run(categorySteps).add_a_category(); }

Test data

Test steps

Call this step for each row

Now run your tests

Displaying the results in easyb

Displaying the results in easyb

Thucydides reports

Browse the features

Browse the stories

Browse the stories

Browse the stories

Browse the test scenarios

Illustrating the test paths

Test scenarios

A test scenario

Steps

Illustrating the test paths

Test scenarios

Test scenario

Steps

Screenshots

Functional coverage

Features

Functional coverage

User stories

Functional coverage

Passing tests

Pending tests

Progress

Functional coverage

Test scenarios

Functional coverage

Referenceseasyb.org

github.com/thucydides-webtests

wakaleo.com/thucydides

The Circle is CompleteAutomated web tests as a team communication tool

John  Ferguson  SmartEmail:  [email protected]:  hCp://www.wakaleo.com

TwiCer:  wakaleo