Top Banner
How to express your requirements as tests, and vice versa Johannes Brodwall
76

How to express your requirements as tests, and vice versa Johannes Brodwall.

Apr 01, 2015

Download

Documents

Amari Cutting
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: How to express your requirements as tests, and vice versa Johannes Brodwall.

How to express your requirements as tests, and vice versaJohannes Brodwall

Page 2: How to express your requirements as tests, and vice versa Johannes Brodwall.

Understanding the problemJohannes Brodwall

Page 3: How to express your requirements as tests, and vice versa Johannes Brodwall.

How to express your requirements as tests, and vice versaJohannes Brodwall

Page 4: How to express your requirements as tests, and vice versa Johannes Brodwall.

FitNesse eksempel #1

Page 5: How to express your requirements as tests, and vice versa Johannes Brodwall.

FitNesse eksempel #1

Page 6: How to express your requirements as tests, and vice versa Johannes Brodwall.

Understanding the problemJohannes Brodwall

Chief Scientist, Steria

Page 7: How to express your requirements as tests, and vice versa Johannes Brodwall.

Background: What’s a requirement?

Page 8: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep9 © Steria

”Why does the customer

want a solution?”

Page 9: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep10 © Steria

Understanding the need

Page 10: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep11 © Steria

Tools:

•Vision statements

•User analysis

Page 11: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep12 © Steria

”What do we implement

when?”

Page 12: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep13 © Steria

Planning

Page 13: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep14 © Steria

Tools:

•Product backlog

•User stories

Page 14: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep15 © Steria

”How should the

functionality work?”

Page 15: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep16 © Steria

Requirement specification

Page 16: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep17 © Steria

Tools:

•Acceptance tests

Page 17: How to express your requirements as tests, and vice versa Johannes Brodwall.

Tests emerge from discussions

Page 18: How to express your requirements as tests, and vice versa Johannes Brodwall.

Example: Electronic signature

Page 19: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep20 © Steria

Developer

Product owner

Tester

Page 20: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep21 © Steria

Developer

Product owner

Tester

Page 21: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep22 © Steria

Developer

Product owner

Tester

As a payment issuer,I want to sign my payments,So that nobody can impersonate me

Page 22: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep23 © Steria

Developer

Product owner

Tester

What about a file that contains both signed and failed payments?

Page 23: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep24 © Steria

Developer

Product owner

Tester

Ummm......(help?)

Page 24: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

Page 25: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep26 © Steria

Developer

Product owner

Tester

Given ....When ....Then ...

Page 26: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep27 © Steria

Developer

Product owner

Tester

Given a file with payment 1 and payment 2And payment 1 is signed correctlyAnd payment 2 is signed incorrectlyWhen the file is validatedThen payment 1 should be processed as usualAnd the payment issuer should receive a receipt indicating payment 2 was rejected

Page 27: How to express your requirements as tests, and vice versa Johannes Brodwall.

An anonymized example from a real project

Page 28: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

FitNesse eksempel #1

Page 29: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

Page 30: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep31 © Steria

Developer

Product owner

Tester

Given ....When ....Then ...

Page 31: How to express your requirements as tests, and vice versa Johannes Brodwall.

A practical example

Page 32: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep33 © Steria

Developer

Product owner

Tester

Given ....When ....Then ...

Cucumber(rspec)

Page 33: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

From my current project:Feature: ”Assign task to me”

Given I go to the work task screen ”team tasks”And I pick the first task with ”SSN” equal ”11111111”And I press the button ”Take task”When I go to the work task screen ”my tasks”Then the work task list should contain 1 taskAnd the ”SSN” of the task should be ”1111111”

Page 34: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

Executed automatically

Given I go to the work task screen ”team tasks”And I pick the first task with ”SSN” equal ”11111111”And I press the button ”Take task”When I go to the work task screen ”my tasks”Then the work task list should contain 1 taskAnd the ”SSN” of the task should be ”1111111”

Page 35: How to express your requirements as tests, and vice versa Johannes Brodwall.

Fictive example: Yahtzee

Page 36: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep37 © Steria

Developer

Product owner

Tester

Full house should give 25 point

Page 37: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

Page 38: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep39 © Steria

Developer

Product owner

Tester

Full house should give 25 point

Page 39: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep40 © Steria

Developer

Product owner

Tester

Is it a full house if five die_values all have the same pipcount?

Page 40: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep41 © Steria

Developer

Product owner

Tester

WTF?!?

Page 41: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

Page 42: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep43 © Steria

Developer

Product owner

Tester

For example five dice all reading 1 is not full house

Ok!

Page 43: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

Page 44: How to express your requirements as tests, and vice versa Johannes Brodwall.

Acceptance tests communicate requirements

Page 45: How to express your requirements as tests, and vice versa Johannes Brodwall.

Developers tests

Page 46: How to express your requirements as tests, and vice versa Johannes Brodwall.

Reflect functional tests

Page 47: How to express your requirements as tests, and vice versa Johannes Brodwall.

Should express requirements (but smaller)

Page 48: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit example: Repository

@Testpublic void shouldRetrieveSameInstanceForSameKey() throws Exception { Category inserted = new Category("A"); Serializable id = repository.insert(inserted); repository.flushChanges();

Category retrieved1 = repository.retrieve(Category.class, id); Category retrieved2 = repository.retrieve(Category.class, id); Category retrieved3 = repository.find(Category.class).iterator().next(); retrieved1.setCategoryName("Z"); assertEquals(retrieved1.getCategoryName(), retrieved2.getCategoryName()); assertEquals(retrieved1.getCategoryName(), retrieved3.getCategoryName());}

Page 49: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

@Testpublic void shouldRetrieveSameInstanceForSameKey() throws Exception { Category inserted = new Category("A"); Serializable id = repository.insert(inserted); repository.flushChanges();

Category retrieved1 = repository.retrieve(Category.class, id); Category retrieved2 = repository.retrieve(Category.class, id); Category retrieved3 = repository.find(Category.class).iterator().next(); retrieved1.setCategoryName("Z"); assertEquals(retrieved1.getCategoryName(), retrieved2.getCategoryName()); assertEquals(retrieved1.getCategoryName(), retrieved3.getCategoryName());}

JUnit: Repository

When I modify one of the retrieved instances

Then the others should be updated, too

Given a database with one object

Given I retrieve this object several times

Page 50: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Repository

@Testpublic void uncommittedInsertsShouldBeInvisibleForOtherThreads() { repository.beginTransaction(); Category category = new Category("A"); repository.insert(category); repository.flushChanges();

assertNull(retrieveInNewThread(Category.class, category.getId()));

repository.commit(); assertEquals(category, retrieveInNewThread(Category.class, category.getId()));}

Page 51: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Repository

@Testpublic void uncommittedInsertsShouldBeInvisibleForOtherThreads() { repository.beginTransaction(); Category category = new Category("A"); repository.insert(category); repository.flushChanges();

assertNull(retrieveInNewThread(Category.class, category.getId()));

repository.commit(); assertEquals(category, retrieveInNewThread(Category.class, category.getId()));}

Given I insert a new object while in a transaction

When I retrieve the object from another thread

Then I should not be able to see it

When I commit the transactionWhen I retrieve the object from another threadThen I should be able to see it

Page 52: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Repository

@Testpublic void uncommittedInsertsShouldBeInvisibleForOtherThreads() { repository.beginTransaction(); Category category = new Category("A"); repository.insert(category); repository.flushChanges();

assertNull(retrieveInNewThread(Category.class, category.getId()));

repository.commit(); assertEquals(category, retrieveInNewThread(Category.class, category.getId()));}

Given I insert a new object while in a transaction

When I retrieve the object from another thread

Then I should not be able to see it

When I commit the transactionWhen I retrieve the object from another threadThen I should be able to see it

Uncommitted Inserts Should

Be Invisible For Other

Threads

Page 53: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Web tests

@Testpublic void listProductsPageShouldShowAll() throws Exception { Product product1 = new Product(uniqueName("product"), 12300); Product product2 = new Product(uniqueName("product"), 300); repository.insertAll(product1, product2); repository.flushChanges();

tester.beginAt("/products/"); tester.assertTextInElement("products", product1.getProductName()); tester.assertTextInElement("products", product2.getProductName());}

Page 54: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Web tests

@Testpublic void listProductsPageShouldShowAll() throws Exception { Product product1 = new Product(uniqueName("product"), 12300); Product product2 = new Product(uniqueName("product"), 300); repository.insertAll(product1, product2); repository.flushChanges();

tester.beginAt("/products/"); tester.assertTextInElement("products", product1.getProductName()); tester.assertTextInElement("products", product2.getProductName());}

Then I should see both products

Given two products with unique names in the database

When I go to the /products/ web page

Page 55: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit : Negative tests

@Test

public void priceMustBeNumeric() throws Exception {

String oldName = uniqueName("product"); int oldPrice = 1234;

Product product = new Product(oldName, oldPrice); Serializable id = repository.insert(product); repository.flushChanges();

tester.beginAt("/products/" + id + "/edit.html"); tester.setTextField("productName", uniqueName("product")); tester.setTextField("price", "this is not a price!"); tester.submit();

tester.assertMatchInElement("errorExplaination", "[Pp]rice .*numeric");

Product stored = repository.retrieve(Product.class, id); assertEquals(oldPrice, stored.getPrice()); assertEquals(oldName, stored.getProductName());}

Page 56: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Negative tests

@Testpublic void priceMustBeNumeric() throws Exception { String oldName = uniqueName("product"); int oldPrice = 1234;

Product product = new Product(oldName, oldPrice); Serializable id = repository.insert(product); repository.flushChanges();

tester.beginAt("/products/" + id + "/edit.html"); tester.setTextField("productName", uniqueName("product")); tester.setTextField("price", "this is not a price!"); tester.submit();

tester.assertMatchInElement("errorExplaination", "[Pp]rice .*numeric");

Product stored = repository.retrieve(Product.class, id); assertEquals(oldPrice, stored.getPrice()); assertEquals(oldName, stored.getProductName());}

Then I should see an error message

Given a product in the database

When I go to the /products/<id>/edit web pageAnd I go change the price to a negative valueAnd I press submit

And the product should be unchanged in the database

Page 57: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep58 © Steria

Developer

Given ....When ....Then ...

Page 58: How to express your requirements as tests, and vice versa Johannes Brodwall.

Good design can be grown

Page 59: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Yahtzee histogram

@Test public void simpleCategoriesShouldBeSumOfMatchingDice() { ... }

@Test public void smallStrait() { ... }

@Test public void largeStrait() { ... }

@Test public void threeOfAKind() { ... }

Page 60: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Yahtzee histogram

@Test public void threeOfAKind() {

assertEquals(0, scoreFor("three_of_a_kind", 1, 1, 2, 2, 3));

assertEquals(3, scoreFor("three_of_a_kind", 1, 1, 1, 2, 3));

assertEquals(6, scoreFor("three_of_a_kind", 2, 2, 2, 3, 3));

assertEquals(9, scoreFor("three_of_a_kind", 1, 1, 3, 3, 3));

}

Page 61: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Yahtzee histogram

@Test public void fullHouse() {

assertEquals(0, scoreFor("full_house", 1, 1, 2, 2, 3));

assertEquals(0, scoreFor("full_house", 1, 1, 1, 2, 3));

assertEquals(25, scoreFor("full_house", 1, 1, 1, 2, 2));

assertEquals(25, scoreFor("full_house", 1, 1, 2, 2, 2));

assertEquals(25, scoreFor("full_house", 5, 5, 6, 6, 6));

}

Page 62: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Yahtzee histogram

@Test public void histogramShouldReturnFrequencyOfEachDie() {

int[] roll = { 1, 1, 2, 3, 4 };

int[] histogram = new ScoreCard().histogram(roll);

assertEquals(7, histogram.length);

assertEquals(-1, histogram[0]);

assertEquals(2, histogram[1]);

assertEquals(1, histogram[2]);

assertEquals(1, histogram[3]);

assertEquals(1, histogram[4]);

assertEquals(0, histogram[5]);

assertEquals(0, histogram[6]);

Page 63: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

JUnit: Yahtzee histogram

scoreCalculators.put("four_of_a_kind", new ScoreCalculator() {

@Override

public int calculate(int[] histogram) {

for (int i=0; i<histogram.length; i++) {

if (histogram[i] >= 4) return i*4;

}

return 0;

}

});

Page 64: How to express your requirements as tests, and vice versa Johannes Brodwall.

Testing: Costs and benefits

Page 65: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep66 © Steria

Ron Jeffries

Only test what you want to work

Page 66: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep67 © Steria

Johannes

Find the defect where it’s cheapest

Page 67: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

Unscientific graph!

Compiler Junit FitNesse System test Prod

Cost

Realism

Page 68: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

Unscientific graph!

Compiler Junit FitNesse System test Prod

Cost

Realism

Chance of finding defects

Page 69: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

Unscientific graph!

Compiler Junit FitNesse System test Prod

Cost

Realism

Cost of running and changing

tests

Page 70: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria

Unscientific graph!

Compiler Junit FitNesse System test Prod

Cost

Realism

Cost of a defect

Page 71: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep72 © Steria

Johannes

Unit tests can reduce maintaince costs. (How?)

Page 72: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep73 © Steria

Johannes

When will unit tests increase maintainance cost?

Page 73: How to express your requirements as tests, and vice versa Johannes Brodwall.

© Steria| 11/04/23 Presentation titlep74 © Steria

Brian Marick

Automated tests are expensive to maintainIf the system wasn’t written to be tested

Page 74: How to express your requirements as tests, and vice versa Johannes Brodwall.

But maintainability is only one reason to test!

Page 75: How to express your requirements as tests, and vice versa Johannes Brodwall.

How to create a good solution?

Page 76: How to express your requirements as tests, and vice versa Johannes Brodwall.

Understand the problem