Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "How to express your requirements as tests, and vice versa Johannes Brodwall."— Presentation transcript:

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

2 Understanding the problem Johannes Brodwall

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

4 FitNesse eksempel #1

5

6 © Steria | 22/10/2014Presentation titlep6 © Steria Agenda (hidden) Wake-up: Why do police and emergency room workers report more incidents during full moons? (Answer: Because they are mistaken) Appertiff: Eksempel acceptance test for payment orders Theme: Wishful thinking Which advantages will we get by writing the test first Which advantages will we get by describing the problem before we attempt to solve it. Which advantages will we get by understanding the problem before we attempt to solve it. Agenda Requirements as tests Tests as requirements Conclusion: How to create a good solution?

7 Understanding the problem Johannes Brodwall Chief Scientist, Steria

8 Background: What’s a requirement?

9 © Steria | 22/10/2014Presentation titlep9 © Steria ”Why does the customer want a solution?”

10 © Steria | 22/10/2014Presentation titlep10 © Steria Understanding the need

11 © Steria | 22/10/2014Presentation titlep11 © Steria Tools: Vision statements User analysis

12 © Steria | 22/10/2014Presentation titlep12 © Steria ”What do we implement when?”

13 © Steria | 22/10/2014Presentation titlep13 © Steria Planning

14 © Steria | 22/10/2014Presentation titlep14 © Steria Tools: Product backlog User stories

15 © Steria | 22/10/2014Presentation titlep15 © Steria ”How should the functionality work?”

16 © Steria | 22/10/2014Presentation titlep16 © Steria Requirement specification

17 © Steria | 22/10/2014Presentation titlep17 © Steria Tools: Acceptance tests

18 Tests emerge from discussions

19 Example: Electronic signature

20 © Steria | 22/10/2014Presentation titlep20 © Steria Developer Product owner Tester

21 © Steria | 22/10/2014Presentation titlep21 © Steria Developer Product owner Tester

22 © Steria | 22/10/2014Presentation titlep22 © Steria Developer Product owner Tester As a payment issuer, I want to sign my payments, So that nobody can impersonate me

23 © Steria | 22/10/2014Presentation titlep23 © Steria Developer Product owner Tester What about a file that contains both signed and failed payments?

24 © Steria | 22/10/2014Presentation titlep24 © Steria Developer Product owner Tester Ummm (help?)

25 © Steria

26 | 22/10/2014Presentation titlep26 © Steria Developer Product owner Tester Given.... When.... Then...

27 © Steria | 22/10/2014Presentation titlep27 © Steria Developer Product owner Tester Given a file with payment 1 and payment 2 And payment 1 is signed correctly And payment 2 is signed incorrectly When the file is validated Then payment 1 should be processed as usual And the payment issuer should receive a receipt indicating payment 2 was rejected

28 An anonymized example from a real project

29 © Steria FitNesse eksempel #1

30 © Steria

31 | 22/10/2014Presentation titlep31 © Steria Developer Product owner Tester Given.... When.... Then...

32 A practical example

33 © Steria | 22/10/2014Presentation titlep33 © Steria Developer Product owner Tester Given.... When.... Then... Cucumber (rspec)

34 © 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 ” ” 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 task And the ”SSN” of the task should be ” ”

35 © Steria Executed automatically Given I go to the work task screen ”team tasks” And I pick the first task with ”SSN” equal ” ” 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 task And the ”SSN” of the task should be ” ”

36 Fictive example: Yahtzee

37 © Steria | 22/10/2014Presentation titlep37 © Steria Developer Product owner Tester Full house should give 25 point

38 © Steria

39 | 22/10/2014Presentation titlep39 © Steria Developer Product owner Tester Full house should give 25 point

40 © Steria | 22/10/2014Presentation titlep40 © Steria Developer Product owner Tester Is it a full house if five die_values all have the same pipcount?

41 © Steria | 22/10/2014Presentation titlep41 © Steria Developer Product owner Tester WTF?!?

42 © Steria

43 | 22/10/2014Presentation titlep43 © Steria Developer Product owner Tester For example five dice all reading 1 is not full house Ok!

44 © Steria

45 Acceptance tests communicate requirements

46 Developers tests

47 Reflect functional tests

48 Should express requirements (but smaller)

49 © Steria JUnit example: public 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()); }

50 © public 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

51 © Steria JUnit: public 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())); }

52 © Steria JUnit: public 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 transaction When I retrieve the object from another thread Then I should be able to see it

53 © Steria JUnit: public 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 transaction When I retrieve the object from another thread Then I should be able to see it Uncommitted Inserts Should Be Invisible For Other Threads

54 © Steria JUnit: Web public 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()); }

55 © Steria JUnit: Web public 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

56 © Steria JUnit : Negative 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()); }

57 © Steria JUnit: Negative 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()); } Then I should see an error message Given a product in the database When I go to the /products/ /edit web page And I go change the price to a negative value And I press submit And the product should be unchanged in the database

58 © Steria | 22/10/2014Presentation titlep58 © Steria Developer Given.... When.... Then...

59 Good design can be grown

60 © Steria JUnit: Yahtzee public void simpleCategoriesShouldBeSumOfMatchingDice() {... public void smallStrait() {... public void largeStrait() {... public void threeOfAKind() {... }

61 © Steria JUnit: Yahtzee 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)); }

62 © Steria JUnit: Yahtzee 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)); }

63 © Steria JUnit: Yahtzee 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]);

64 © Steria JUnit: Yahtzee histogram scoreCalculators.put("four_of_a_kind", new ScoreCalculator() public int calculate(int[] histogram) { for (int i=0; i= 4) return i*4; } return 0; } });

65 Testing: Costs and benefits

66 © Steria | 22/10/2014Presentation titlep66 © Steria Ron Jeffries Only test what you want to work

67 © Steria | 22/10/2014Presentation titlep67 © Steria Johannes Find the defect where it’s cheapest

68 © Steria Unscientific graph!

69 © Steria Unscientific graph! Chance of finding defects

70 © Steria Unscientific graph! Cost of running and changing tests

71 © Steria Unscientific graph! Cost of a defect

72 © Steria | 22/10/2014Presentation titlep72 © Steria Johannes Unit tests can reduce maintaince costs. (How?)

73 © Steria | 22/10/2014Presentation titlep73 © Steria Johannes When will unit tests increase maintainance cost?

74 © Steria | 22/10/2014Presentation titlep74 © Steria Brian Marick Automated tests are expensive to maintain If the system wasn’t written to be tested

75 But maintainability is only one reason to test!

76 How to create a good solution?

77 Understand the problem


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

Similar presentations


Ads by Google