6. User stories
As a job seeker
I want to find jobs in relevant categories
So that I can find a suitable job
Friday, 9 March 12
7. User stories
As a job seeker
I want to find jobs in relevant categories
So that I can find a suitable job
Features/Epics
Friday, 9 March 12
8. User stories
As a job seeker
I want to find jobs in relevant categories
So that I can find a suitable job
Acceptance criteria
☑
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
Friday, 9 March 12
9. User stories
As a job seeker
I want to find jobs in relevant categories
So that I can find a suitable job
Acceptance criteria
☑
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
Friday, 9 March 12
10. 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
Friday, 9 March 12
11. 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
Implemented development tests
Friday, 9 March 12
12. 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
Implemented development tests Implemented acceptance tests
Friday, 9 March 12
36. How do we bridge the gap?
Test steps
Friday, 9 March 12
37. 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
Test steps
Friday, 9 March 12
38. 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
Test steps
Friday, 9 March 12
39. 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
JobSeekerSteps
JobSeekerSteps
open_jobs_page()
Test steps
open_jobs_page()
open_jobs_page()
should_see_job_categories(String...
categories)
should_see_job_categories(String...
categories)
... should_see_job_categories(String...
categories)
...
...
Step libraries
Friday, 9 March 12
40. 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 Tests
JobSeekerSteps
JobSeekerSteps
JobSeekerSteps
open_jobs_page()
open_jobs_page()
open_jobs_page()
should_see_job_categories(String...
categories)
should_see_job_categories(String...
categories)
... should_see_job_categories(String...
categories)
...
...
Step libraries
Test steps
Friday, 9 March 12
41. 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 Tests
JobSeekerSteps
JobSeekerSteps
JobSeekerSteps
open_jobs_page()
open_jobs_page()
open_jobs_page()
should_see_job_categories(String...
categories)
should_see_job_categories(String...
categories)
... should_see_job_categories(String...
categories)
...
...
Step libraries
Test steps
Page Objects
Friday, 9 March 12
63. Defining your acceptance tests
scenario "A
job seeker
{ can see the
available j
ob categori
when "the j es on the h
ob seeker i ome page",
then "the j s looking f
ob seeker c o r a j o b ",
} an see all
the availab
le job cate
gories"
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",
}
scenario "The admini
strator deletes a ca
{ tegory from the syst
em",
given "a category ne
eds to be deleted",
when "the administra
tor deletes a catego
then "the system will ry",
confirm that the cate
and "the deleted cate gory has been delete
gory should no longer d",
} be visible to job se
eker s",
Friday, 9 March 12
64. Defining your acceptance tests
scenario "A
job seeker
{ can see the
available j
ob categori
when "the j es on the h
ob seeker i ome page",
then "the j s looking f
ob seeker c o r a j o b ",
} an see all
the availab
le job cate
gories"
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",
}
scenario "The admini
strator deletes a ca
{ tegory from the syst
em",
given "a category ne
eds to be deleted",
when "the administra
tor deletes a catego
then "the system will ry",
confirm that the cate
and "the deleted cate gory has been delete
gory should no longer d",
} be visible to job se
eker s",
focus on business value
Friday, 9 March 12
65. Defining your acceptance tests
scenario "A
job seeker
{ can see the
available j
ob categori
when "the j es on the h
ob seeker i ome page",
then "the j s looking f
ob seeker c o r a j o b ",
} an see all
the availab
le job cate
gories"
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",
}
{
scenario "The admini
strator deletes a ca
tegory from the syst
em",
...defined in business terms
given "a category ne
eds to be deleted",
when "the administra
tor deletes a catego
then "the system will ry",
confirm that the cate
and "the deleted cate gory has been delete
gory should no longer d",
} be visible to job se
eker s",
focus on business value
Friday, 9 March 12
66. Defining your acceptance tests
scenario "A
job seeker
{ can see the
available j
ob categori
when "the j es on the h
ob seeker i ome page",
then "the j s looking f
ob seeker c o r a j o b ",
} an see all
the availab
le job cate
gories"
High level requ
irements...
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",
}
{
scenario "The admini
strator deletes a ca
tegory from the syst
em",
...defined in business terms
given "a category ne
eds to be deleted",
when "the administra
tor deletes a catego
then "the system will ry",
confirm that the cate
and "the deleted cate gory has been delete
gory should no longer d",
} be visible to job se
eker s",
focus on business value
Friday, 9 March 12
67. 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 {}
}
}
Friday, 9 March 12
68. Organizing your requirements
Features 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 {}
}
}
Friday, 9 March 12
69. Organizing your requirements
Features 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 Stories
public class BrowseJobs {
public class UserLookForJobs {}
public class UserBrowsesJobTabs {}
}
}
Friday, 9 March 12
70. Organizing your requirements
Features 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 Stories
public class BrowseJobs {
public class UserLookForJobs {}
public class UserBrowsesJobTabs {}
}
}
Friday, 9 March 12
71. Implementing your acceptance tests
using "thucydides"
thucydides.uses_steps_from AdministratorSteps
thucydides.uses_steps_from JobSeekerSteps
thucydides.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"
}
}
Friday, 9 March 12
72. Implementing your acceptance tests
using "thucydides" We are testing this story
thucydides.uses_steps_from AdministratorSteps
thucydides.uses_steps_from JobSeekerSteps
thucydides.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"
}
}
Friday, 9 March 12
73. Implementing your acceptance tests
using "thucydides" We are testing this story
thucydides.uses_steps_from AdministratorSteps
thucydides.uses_steps_from JobSeekerSteps
thucydides.tests_story AddNewCategory
An acceptance criteria
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"
}
}
Friday, 9 March 12
74. Implementing your acceptance tests
using "thucydides" We are testing this story
thucydides.uses_steps_from AdministratorSteps
thucydides.uses_steps_from JobSeekerSteps
thucydides.tests_story AddNewCategory
An acceptance criteria
scenario "The administrator adds a new category to the system",
{
given "a new category needs to be added to the system",
{
Narrative style
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"
}
}
Friday, 9 March 12
75. Implementing your acceptance tests
using "thucydides" We are testing this story
thucydides.uses_steps_from AdministratorSteps
thucydides.uses_steps_from JobSeekerSteps
thucydides.tests_story AddNewCategory
An acceptance criteria
scenario "The administrator adds a new category to the system",
{
given "a new category needs to be added to the system",
{
Narrative style
administrator.logs_in_to_admin_page_if_first_time()
administrator.opens_categories_list()
} Step through an
when "the administrator adds a new category", example
{
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"
}
}
Friday, 9 March 12
76. Implementing your acceptance tests
using "thucydides" We are testing this story
thucydides.uses_steps_from AdministratorSteps
thucydides.uses_steps_from JobSeekerSteps
thucydides.tests_story AddNewCategory
An acceptance criteria
scenario "The administrator adds a new category to the system",
{
given "a new category needs to be added to the system",
{
Narrative style
administrator.logs_in_to_admin_page_if_first_time()
administrator.opens_categories_list()
} Step through an
when "the administrator adds a new category", example
{
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",
{ Still high-level
job_seeker.opens_jobs_page()
job_seeker.should_see_job_category "Scala Developers"
}
}
Friday, 9 March 12
77. 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() {}
}
Friday, 9 March 12
78. Some folks prefer JUnit...
@RunWith(ThucydidesRunner.class)
@Story(AddNewCategory.class) Thucydides handles the
public class AddCategoryStory {
web driver instances
@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() {}
}
Friday, 9 March 12
79. Some folks prefer JUnit...
@RunWith(ThucydidesRunner.class)
@Story(AddNewCategory.class) Thucydides handles the
public class AddCategoryStory {
web driver instances
@Managed
public WebDriver webdriver;
@ManagedPages(defaultUrl = "http://localhost:9000")
public Pages pages;
@Steps
public AdministratorSteps administrator;
@Steps
Using the same 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() {}
}
Friday, 9 March 12
80. Some folks prefer JUnit...
@RunWith(ThucydidesRunner.class)
@Story(AddNewCategory.class) Thucydides handles the
public class AddCategoryStory {
web driver instances
@Managed
public WebDriver webdriver;
@ManagedPages(defaultUrl = "http://localhost:9000")
public Pages pages;
@Steps
public AdministratorSteps administrator;
@Steps
Using the same 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");
} Tests can be pending
@Pending @Test
public void administrator_adds_an_existing_category_to_the_system() {}
}
Friday, 9 March 12
81. Defining your test steps
public 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);
}
@Step
public void deletes_category(String name) {
opens_categories_list();
displays_category_details_for(name);
deletes_category();
}
}
Friday, 9 March 12
82. Defining your test steps
public class AdministratorSteps extends ScenarioSteps { A step library
@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);
}
@Step
public void deletes_category(String name) {
opens_categories_list();
displays_category_details_for(name);
deletes_category();
}
}
Friday, 9 March 12
83. Defining your test steps
public class AdministratorSteps extends ScenarioSteps { A step library
@Step
public void opens_categories_list() {
AdminHomePage page = getPages().get(AdminHomePage.class);
page.open();
page.selectObjectType("Categories");
} High level steps...
@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);
}
@Step
public void deletes_category(String name) {
opens_categories_list();
displays_category_details_for(name);
deletes_category();
}
}
Friday, 9 March 12
84. Defining your test steps
public class AdministratorSteps extends ScenarioSteps { A step library
@Step
public void opens_categories_list() {
AdminHomePage page = getPages().get(AdminHomePage.class);
page.open();
page.selectObjectType("Categories");
} High level steps...
@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);
}
...implemented
@Step
public void should_see_confirmation_message(String message) {
with Page Objects
AdminPage page = getPages().get(AdminPage.class);
page.shouldContainConfirmationMessage(message);
}
@Step
public void deletes_category(String name) {
opens_categories_list();
displays_category_details_for(name);
deletes_category();
}
}
Friday, 9 March 12
85. Defining your test steps
public class AdministratorSteps extends ScenarioSteps { A step library
@Step
public void opens_categories_list() {
AdminHomePage page = getPages().get(AdminHomePage.class);
page.open();
page.selectObjectType("Categories");
} High level steps...
@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);
}
...implemented
@Step
public void should_see_confirmation_message(String message) {
with Page Objects
AdminPage page = getPages().get(AdminPage.class);
page.shouldContainConfirmationMessage(message);
}
@Step ...or with other steps
public void deletes_category(String name) {
opens_categories_list();
displays_category_details_for(name);
deletes_category();
}
}
Friday, 9 March 12
86. Defining your page objects
public 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();
}
}
Friday, 9 March 12
87. Defining your page objects
public class EditCategoryPage extends PageObject {
@FindBy(id="object_label")
WebElement label; Provides some useful
@FindBy(id="object_code")
utility methods...
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();
}
}
Friday, 9 March 12
88. Defining your page objects
public class EditCategoryPage extends PageObject {
@FindBy(id="object_label")
WebElement label; Provides some useful
@FindBy(id="object_code")
utility methods...
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();
}
} but otherwise a normal
WebDriver Page Object
Friday, 9 March 12