39
1 1 Copyright 2014 Gerard Meszaros http://craft2014.testAutomationPatterns.com Maximizing Expressiveness of Automated Tests Gerard Meszaros Independent Consultant CTO of FeedXL.Com [email protected] These Slides: http://craft2014.testAutomationPatterns.com 2 Copyright 2014 Gerard Meszaros http://craft2014.testAutomationPatterns.com Product & I.T. I.T. Embedded Telecom My Background Gerard Meszaros [email protected] Software developer Development manager Project Manager Software architect OOA/OOD Mentor Requirements (Use Case) Mentor XP/TDD Mentor Agile PM Mentor Test Automation Consultant & Trainer Lean/Agile Coach/Consultant

Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

1

1 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Maximizing Expressiveness ofAutomated Tests

Gerard MeszarosIndependent Consultant

CTO of [email protected]

These Slides:http://craft2014.testAutomationPatterns.com

2 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Product & I.T.

I.T.

EmbeddedTelecom

My Background

Gerard [email protected]

•Software developer

•Development manager

•Project Manager

•Software architect

•OOA/OOD Mentor

•Requirements (Use Case) Mentor

•XP/TDD Mentor

•Agile PM Mentor

•Test Automation Consultant & Trainer

•Lean/Agile Coach/Consultant

Page 2: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

2

3 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Agenda• Motivation

– Why Test Craftsmanship Matters• Managing Scope vs Detail

– In Functional (Acceptance) Tests• Achieving a Test-Friendly Architecture• Managing Scope vs Detail

– In Unit Tests

4 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Do Your Tests Look Like:public void testAddItemQuantity_severalQuantity () throws Exception {

try {

// Setup Fixturefinal int QUANTITY = 5;Address billingAddress = new Address("1222 1st St SW",

"Calgary", "Alberta", "T2N 2V2", "Canada");Address shippingAddress = new Address("1333 1st St

SW", "Calgary", "Alberta", "T2N 2V2","Canada");

Customer customer = new Customer(99, "John", "Doe",new BigDecimal("30"), billingAddress,shippingAddress);

Product product = new Product(88, "SomeWidget", newBigDecimal("19.99"));

Invoice invoice = new Invoice(customer);// Exercise SUTinvoice.addItemQuantity(product, QUANTITY);// Verify OutcomeList lineItems = invoice.getLineItems();if (lineItems.size() == 1) {LineItem actualLineItem =

(LineItem)lineItems.get(0);assertEquals(invoice, actualLineItem.getInvoice());assertEquals(product, actualLineItem.getProduct());assertEquals(quantity,

actualLineItem.getQuantity());assertEquals(new BigDecimal("30"),

actualLineItem.getPercentDiscount());assertEquals(new BigDecimal("19.99"),

actualLineItem.getUnitPrice());assertEquals(new BigDecimal(“69.96"),

actualLineItem.getExtendedPrice());} else {assertTrue(“Invoice should have exactly one line

item“, false);}

} finally {

deleteObject(expectedLineItem);deleteObject(invoice);deleteObject(product);deleteObject(customer);deleteObject(billingAddress);deleteObject(shippingAddress);

:}

You might be questioning their value!

Page 3: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

3

5 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Where Automation Provides Value• Detecting Differences

– Find unexpected differences between differentenvironments (e.g. different browsers)

• “Pin the functionality”– Find unexpected changes between versions as the

product evolves over time• Avoid Wasting Effort

– testing manually when known issues exist– Testing things manually when it could be automated– Focus manual test effort on what automation doesn’t

6 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Where Automation Provides Value (2)• Communicating Expectations

– Avoid building the wrong product– Behaviour / Example-Driven Development (BDD / EDD)– Acceptance Test Driven Development (ATDD)

• Find Issues Sooner– By running the tests more frequently (ideally after every

change)– Enabled by full automation (near zero cost)– Requires robust test automation

Page 4: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

4

7 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Where Automation Adds Cost• Direct Costs:

– Cost to write tests initially– Cost to investigate failing tests– Cost to fix failing tests

• Exacerbated by:– Too Many Tests– Too Fragile Tests– Too Complex Tests

8 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

TestAutomation

Effort

After Automation

Economics of Maintainability

Test Automation is a lot easier to sell on• Cost reduction than• Software Quality Improvement or• Quality of Life Improvement

DevelopmentEffort

saved effort

time

Increasedeffort(Hump) Ongoing

effortInitialeffort

Cost of TestAutomation + Ongoing

Maintenance

Page 5: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

5

9 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

TestAutomation

Effort

saved effort

Economics of Maintainability

Test Automation is a lot easier to sell on• Cost reduction than• Software Quality Improvement or• Quality of Life Improvement

time

Initialeffort

Ongoingeffort

Cost of TestAutomation + Ongoing

Maintenance

Increasedeffort(Hump)

Unsustainable Automation

DevelopmentEffort

10 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Agenda• Motivation• Managing Scope vs Detail

– In Functional (Acceptance) Tests• Achieving a Test-Friendly Architecture• Managing Scope vs Detail

– In Unit Tests

Page 6: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

6

11 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Test Automation Pyramid

Unit Tests

ComponentTests

SystemTests

Pyramid originally proposed by Mike Cohn

Exploratory Tests

• Large numbers of verysmall unit tests– Ensures integrity of code

• Smaller number offunctional tests for majorcomponents– Verify integration of units

• Even fewer tests for theentire application &workflow– Ensure application(s) support

users’ requirements• Tools to support effective

exploratory testing

12 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Need to specify at the right detail and scope.Behavior Specification at Right Level

Broad Narrow

Detail

High

L

ow

Scope

Unit Tests

ComponentTests

SystemTests

Exploratory Tests

Page 7: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

7

13 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Need to specify at the right detail and scope.Behavior Specification at Right Level

Broad Narrow

Detail

High

L

ow

Scope

ComponentTests

SystemTests

14 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

ComponentTests

SystemTests

• Specify broad scope at minimum detail• Specify most detailed req’ts at narrowest scope

Behavior Specification at Right Level

Rules &Algorithms

Multi-Use Case

WorkflowsTransactions(Use Cases)

IncompleteSpec

Toomuch detailUnmaintainableBroad Narrow

Detail

High

L

ow

Scope

Page 8: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

8

15 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Use Cases & User Stories

ConfigureNotification

Rules

SuspendNotification

ResumeNotification

AccountHolder

ProcessTransaction

TransactionSettlement

Not

ify

base

d on

cha

rge

Type

Not

ify

base

d on

cha

rge

Cont

inen

tN

otif

y ba

sed

on c

harg

e Co

untr

yN

otif

y ba

sed

on c

harg

e Ci

ty &

Sta

te

Susp

end

Not

ific

atio

n

16 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Testing Notifications - 1Given:

User and Accounts

Example:

When:Notification

Rule is Configured

Then:Notification RuleConfigured and

Active

Then:Notification Rule

is Active

Page 9: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

9

17 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Testing Notifications - 2

Then: ExpectedNotifications

Broad Scope (Multi-Actor);Medium Detail (Too much for the scope)

Example:

When: TheTransactions tobe processed

Use Case:Process

Transactions

18 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Issues With This Test• Difficult to understand which TX’s should notify

– because cause (rules) and effect (notification) are farapart

• Only verifies one simple combination of rules– We will require many more tests to test all the other

combinations– Lots of repetition of workflow & data across test cases

• Simplest workflow;– More complex workflows will be even longer and harder

to understand• Tests will take a long time to run

– Due to need to configure first, then run transactionprocessing

Page 10: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

10

19 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

What Can We Do?• Make tests shorter

– Fewer steps• Make tests less detailed

– Omit unnecessary information• Focus tests on specific aspects

of behaviour– Test/Spec Algorithms & Rules directly– Test less functionality, but more

thoroughly

Fine advice, but too vague

Raising abstractionlevel can help with this

and with this

RequiresTest-FriendlyArchitecture

20 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Changing Level of Abstraction/Detail• Too detailed for verifying workflow and• Too broadly scoped for checking the rules• Need to Reduce Detail or Reduce Scope

Rules &Algorithms

Multi-Use Case

WorkflowsTransactions(Use Cases)

Toomuch detailUnmaintainable

IncompleteSpec

Broad Narrow

Detail

High

L

ow

Scope

Page 11: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

11

21 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Omitting Unnecessary Information• Ask not what you can include in a test…

• Ask instead:

• What can I leave out of this test?

“If it isn’t essential to conveying the essence ofthe behavior, it is essential to not include it.”

22 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Specifying WorkflowGiven:

User and Accounts

Example:

When:Notification

Rule is Configured

Then:Notification RuleConfigured and

Active

Then:Notification Rule

is Active

Page 12: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

12

23 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Specifying WorkflowExample:

24 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Specifying Workflow

Then: ExpectedNotifications

Example:

When: TheTransactions tobe processed

Use Case:Process

Transactions

Page 13: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

13

25 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Specifying WorkflowExample:

26 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Specifying WorkflowExample:

Page 14: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

14

27 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Specifying Notification WorkflowExample:

Broad Scope (Multi-Actor);Minimum Detail (per Actor/Transaction);

Given:User &

Thresholds

When:Transactions

Are Processed

Then:We Expect

Notifications

The overall workflow should be defined at a very high level

credit

credit

28 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Specifying Suspension WorkflowGiven BobMa has set notification threshold to $10,000

for all transactions on his accountWhen the bank processes debit for 15,000 to his accountThen BobMa receives notification for debit 15,000

When BobMa suspends notificationAnd the bank processes debit for 15,000 to his accountThen BobMa receives no notification

When BobMa resumes notificationAnd the bank processes debit for 15,000 to his accountThen BobMa receives notification for debit 15,000Broad Scope; Minimum Detail;

Irrelevant Details Omitted!

Over threshold

Over threshold

Over threshold

Page 15: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

15

29 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Changing Level of Abstraction/Detail• So, where should omitted details go?

Rules &Algorithms

Multi-Use Case

WorkflowsTransactions(Use Cases)

IncompleteSpec

Toomuch detailUnmaintainableBroad Narrow

Detail

High

L

ow

Scope

30 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Single Use Case TestUse Case:

ManageNotifications

Data to be shown onManage Accounts Tab

Side effect of AddingA Notification

Medium Scope (Single Actor)Medium Detail (Transaction, not UI);

Example:

Data to be shown onManage Accounts Tab

Data to be shownon Manage

Notifications Tab

Page 16: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

16

31 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Changing Level of Abstraction/Detail• Need the detail to specify notification rules• Therefore, need to reduce scope even more

Rules &Algorithms

Multi-Use Case

WorkflowsTransactions(Use Cases)

IncompleteSpec

Toomuch detailUnmaintainableBroad Narrow

Detail

High

L

ow

Scope

32 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Business Rule Specs

Configuration Process TransactionThreshold per Charge Type

Narrow Scope (Single Rule)High Detail (Everything that matters)

Example:

Given theserules

When we askNotificationRequired?with this transaction:

Then: Theanswer should be

Page 17: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

17

33 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Agenda• Motivation• Managing Scope vs Detail

– In Functional (Acceptance) Tests• Achieving a Test-Friendly Architecture• Managing Scope vs Detail

– In Unit Tests

34 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

• Must test through User Interface• Must load lots of data

Test - After Architecture

System Under Test

Should weNotify?Process

Transaction

ConfigureNotificationThreshold

NotificationRules

TransactionInterface

ConfigurationUser

Interface

NotificationLog

WorkflowTest

DoNotification.

Page 18: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

18

35 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

• Need to provide API’s to invoke functionalitydirectly bypassing the UI

• Supports Workflow and• Use Case / Transaction test automation

System Under Test

Test-Driven Architecture

Should weNotify?

DoNotification.

ProcessTransaction

ConfigureNotificationThreshold

NotificationRules

NotificationLog

TransactionInterface

ConfigurationUser

InterfaceWorkflow

Test

36 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Test-Driven Architecture – Use Case Tests

System Under Test

• Same API supports Transaction (Use Case)tests:

Should weNotify?

DoNotification.

ProcessTransaction

ConfigureNotificationThreshold

NotificationRules

NotificationLog

TransactionInterface

ConfigurationUser

Interface

ConfigurationTX Test

Page 19: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

19

37 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Test-Driven Architecture – Business Rules• Encapsulation of Rules in “Rules Component”

• which can be accessed directly via the Test

Should weNotify?

DoNotification.

ProcessTransaction

ConfigureNotificationThreshold

NotificationRules

NotificationLog

TransactionInterface

ConfigurationUser

Interface

NotificationMethod Test

NotificationRules FakeSystem Under Test

NotificationRule Test

38 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

• Encapsulation of Rules in “Rules Component”• which can be accessed directly via the Test

• Component Accept Rules via “Data Injection”– Simplify Test Automation by avoiding need to configure

• Forces Design-for-testability– Only When Automation a Dev’t Responsibility

Business Rules Tests Encourage:

Should weNotify?

NotificationRules Fake

NotificationRule Test

Page 20: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

20

39 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Agenda• Motivation• Managing Scope vs Detail

– In Functional (Acceptance) Tests• Achieving a Test-Friendly Architecture• Managing Scope vs Detail

– In Unit Tests

40 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

(Non-)Maintainable Test Codepublic void testAddItemQuantity_severalQuantity ()

throws Exception {try {

// Setup Fixturefinal int QUANTITY = 5;Address billingAddress = new Address("1222 1st St

SW", "Calgary", "Alberta", "T2N 2V2","Canada");

Address shippingAddress = new Address("1333 1stSt SW", "Calgary", "Alberta", "T2N 2V2","Canada");

Customer customer = new Customer(99, "John","Doe", new BigDecimal("30"),billingAddress, shippingAddress);

Product product = new Product(88, "SomeWidget",new BigDecimal("19.99"));

Invoice invoice = new Invoice(customer);// Exercise SUTinvoice.addItemQuantity(product, QUANTITY);// Verify OutcomeList lineItems = invoice.getLineItems();if (lineItems.size() == 1) {LineItem actualLineItem =

(LineItem)lineItems.get(0);assertEquals(invoice,

actualLineItem.getInvoice());assertEquals(product,

actualLineItem.getProduct());assertEquals(quantity,

actualLineItem.getQuantity());assertEquals(new BigDecimal("30"),

actualLineItem.getPercentDiscount());assertEquals(new BigDecimal("19.99"),

actualLineItem.getUnitPrice());assertEquals(new BigDecimal(“69.96"),

actualLineItem.getExtendedPrice());} else {assertTrue(“Invoice should have exactly one

line item“, false);}

:}

public voidtestAddItemQuantity_severalQuantity (){// Given:

QUANTITY = 5 ;product = givenAnyProduct();invoice = givenAnEmptyInvoice();// When:invoice.addItemQuantity(

product, QUANTITY);// Then:assertExactlyOneLineItem(

invoice,expectedItem(

invoice,product, QUANTITY,product.getPrice()*

QUANTITY) );}

Page 21: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

21

41 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Example

• Test addItemQuantity and removeLineItemmethods of Invoice

CustomerFirstNameLastNameDiscount

InvoiceAddressshipping

billing

1

billing

Product

LineItemQuantityUnitPrice

ExtendedPricePercentDiscount

invoicesinvoicedCustomer

shipping

42 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

The Whole Testpublic void testAddItemQuantity_severalQuantity () throws Exception {

// Setup Fixturefinal int QUANTITY = 5;Address billingAddress = new Address("1222 1st St SW", "Calgary",

"Alberta", "T2N 2V2", "Canada");Address shippingAddress = new Address("1333 1st St SW", "Calgary",

"Alberta", "T2N 2V2", "Canada");Customer customer = new Customer(99, "John", "Doe", new BigDecimal("30"),

billingAddress, shippingAddress);Product product = new Product(88, "SomeWidget", new BigDecimal("19.99"));Invoice invoice = new Invoice(customer);// Exercise SUTinvoice.addItemQuantity(product, QUANTITY);// Verify OutcomeList lineItems = invoice.getLineItems();if (lineItems.size() == 1) {

LineItem actualLineItem = (LineItem)lineItems.get(0);assertEquals(invoice, actualLineItem.getInvoice());assertEquals(product, actualLineItem.getProduct());assertEquals(quantity, actualLineItem.getQuantity());assertEquals(new BigDecimal("30"), actualLineItem.getPercentDiscount());assertEquals(new BigDecimal("19.99"), actualLineItem.getUnitPrice());assertEquals(new BigDecimal(“69.96"),

actualLineItem.getExtendedPrice());} else {

assertTrue(“Invoice should have exactly one line item“, false);} :

}

Given: ???

When we calladdItemQuantity

Then: ???

Page 22: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

22

43 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Obtuse Assertion

Verifying the Outcome

List lineItems = invoice.getLineItems();

if (lineItems.size() == 1) {

LineItem actualLineItem = (LineItem)lineItems.get(0);

assertEquals(invoice, actualLineItem.getInvoice());

assertEquals(product, actualLineItem.getProduct());

assertEquals(quantity, actualLineItem.getQuantity());

assertEquals(new BigDecimal("30"),actualLineItem.getPercentDiscount());

assertEquals(new BigDecimal("19.99"),actualLineItem.getUnitPrice());

assertEquals(new BigDecimal(“69.96"),actualLineItem.getExtendedPrice());

} else {

assertTrue(“Invoice should have exactly one line item“,false);

}

44 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Use Better Assertion

List lineItems = invoice.getLineItems();

if (lineItems.size() == 1) {

LineItem actualLineItem = (LineItem)lineItems.get(0);

assertEquals(invoice, actualLineItem.getInvoice());

assertEquals(product, actualLineItem.getProduct());

assertEquals(quantity, actualLineItem.getQuantity());

assertEquals(new BigDecimal("30"),actualLineItem.getPercentDiscount());

assertEquals(new BigDecimal("19.99"),actualLineItem.getUnitPrice());

assertEquals(new BigDecimal(“69.96"),actualLineItem.getExtendedPrice());

} else {

fail("invoice should have exactly one line item");

}}

Refactoring

Page 23: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

23

45 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Hard-WiredTest Data

Use Better Assertion

List lineItems = invoice.getLineItems();

if (lineItems.size() == 1) {

LineItem actualLineItem = (LineItem)lineItems.get(0);

assertEquals(invoice, actualLineItem.getInvoice());

assertEquals(product, actualLineItem.getProduct());

assertEquals(quantity, actualLineItem.getQuantity());

assertEquals(new BigDecimal("30"),actualLineItem.getPercentDiscount());

assertEquals(new BigDecimal("19.99"),actualLineItem.getUnitPrice());

assertEquals(new BigDecimal(“69.96"),actualLineItem.getExtendedPrice());

} else {

fail("invoice should have exactly one line item");

}}

Fragile Tests

Refactoring

46 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Expected Object

List lineItems = invoice.getLineItems();

if (lineItems.size() == 1) {

LineItem actualLineItem = (LineItem)lineItems.get(0);

LineItem expectedLineItem =newLineItem(invoice, product, QUANTITY);

assertEquals(expectedLineItem.getInvoice(),actualLineItem.getInvoice());

assertEquals(expectedLineItem.getProduct(),actualLineItem.getProduct());

assertEquals(expectedLineItem.getQuantity(),actualLineItem.getQuantity());

assertEquals(expectedLineItem.getPercentDiscount(),actualLineItem.getPercentDiscount());

assertEquals(expectedLineItem.getUnitPrice(),actualLineItem.getUnitPrice());

assertEquals(expectedLineItem.getExtendedPrice(),actualLineItem.getExtendedPrice());

} else {

fail("invoice should have exactly one line item");

}}

Pattern

Page 24: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

24

47 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Verbose Test

Expected Object

List lineItems = invoice.getLineItems();

if (lineItems.size() == 1) {

LineItem actualLineItem = (LineItem)lineItems.get(0);

LineItem expectedLineItem = newLineItem(invoice,product, QUANTITY, product.getPrice()*QUANTITY );

assertEquals(expectedLineItem.getInvoice(),actualLineItem.getInvoice());

assertEquals(expectedLineItem.getProduct(),actualLineItem.getProduct());

assertEquals(expectedLineItem.getQuantity(),actualLineItem.getQuantity());

assertEquals(expectedLineItem.getPercentDiscount(),actualLineItem.getPercentDiscount());

assertEquals(expectedLineItem.getUnitPrice(),actualLineItem.getUnitPrice());

assertEquals(expectedLineItem.getExtendedPrice(),actualLineItem.getExtendedPrice());

} else {

fail("invoice should have exactly one line item");

}}

Pattern

48 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Introduce Custom Assert

List lineItems = invoice.getLineItems();

if (lineItems.size() == 1) {

LineItem actualLineItem = (LineItem)lineItems.get(0);

LineItem expectedLineItem = newLineItem(invoice,product, QUANTITY, product.getPrice()*QUANTITY );

assertLineItemsEqual(expectedLineItem, actualLineItem);

} else {

fail("invoice should have exactly one line item");

}

Refactoring

CustomAssertion

Page 25: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

25

49 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

ConditionalTest LogicConditionalTest Logic

Introduce Custom Assert

List lineItems = invoice.getLineItems();

if (lineItems.size() == 1) {

LineItem actualLineItem = (LineItem)lineItems.get(0);

LineItem expectedLineItem = newLineItem(invoice,product, QUANTITY, product.getPrice()*QUANTITY );

assertLineItemsEqual(expectedLineItem, actualLineItem);

} else {

fail("invoice should have exactly one line item");

}

Refactoring

50 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Replace Conditional Logic with Guard Assertion

List lineItems = invoice.getLineItems();

assertEquals("number of items",lineItems.size(),1);

LineItem actualLineItem = (LineItem)lineItems.get(0);

LineItem expectedLineItem = newLineItem(invoice,product, QUANTITY, product.getPrice()*QUANTITY );

assertLineItemsEqual(expectedLineItem, actualLineItem);

Refactoring

Page 26: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

26

51 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

The Whole Testpublic void testAddItemQuantity_severalQuantity () throws Exception {

// Setup Fixturefinal int QUANTITY = 5;Address billingAddress = new Address("1222 1st St SW", "Calgary",

"Alberta", "T2N 2V2", "Canada");Address shippingAddress = new Address("1333 1st St SW",

"Calgary", "Alberta", "T2N 2V2", "Canada");Customer customer = new Customer(99, "John", "Doe", new

BigDecimal("30"), billingAddress, shippingAddress);Product product = new Product(88, "SomeWidget", new

BigDecimal("19.99"));Invoice invoice = new Invoice(customer);// Exercise SUTinvoice.addItemQuantity(product, QUANTITY);// Verify Outcome

assertEquals("number of items",lineItems.size(),1);

LineItem actualLineItem = (LineItem)lineItems.get(0);

LineItem expectedLineItem = newLineItem(invoice, product,QUANTITY);

assertLineItemsEqual(expectedLineItem, actualLineItem);}

52 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Hard-Coded Test Datapublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5;

Address billingAddress = new Address("1222 1st St SW","Calgary", "Alberta", "T2N 2V2", "Canada");

Address shippingAddress = new Address("1333 1st St SW","Calgary", "Alberta", "T2N 2V2", "Canada");

Customer customer = new Customer(99, "John", "Doe", newBigDecimal("30"), billingAddress, shippingAddress);

Product product = new Product(88, "SomeWidget", newBigDecimal("19.99"));

Invoice invoice = new Invoice(customer);

// Exercise SUT

invoice.addItemQuantity(product, QUANTITY);

Hard-codedTest Data

(Obscure Test)

UnrepeatableTests

Code Smell

Page 27: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

27

53 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Distinct Generated Valuespublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5 ;

Address billingAddress = new Address(getUniqueString(),getUniqueString(), getUniqueString(),getUniqueString(), getUniqueString());

Address shippingAddress = new Address(getUniqueString(),getUniqueString(), getUniqueString(),getUniqueString(), getUniqueString());

Customer customer = new Customer(getUniqueInt(), getUniqueString(),getUniqueString(), getUniqueDiscount(),billingAddress, shippingAddress);

Product product = new Product(getUniqueInt(), getUniqueString(),getUniqueNumber());

Invoice invoice = new Invoice(customer);

Pattern

54 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Distinct Generated Valuespublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5 ;

Address billingAddress = new Address(getUniqueString(),getUniqueString(), getUniqueString(),getUniqueString(), getUniqueString());

Address shippingAddress = new Address(getUniqueString(),getUniqueString(), getUniqueString(),getUniqueString(), getUniqueString());

Customer customer1 = new Customer(getUniqueInt(), getUniqueString(),getUniqueString(), getUniqueDiscount(),billingAddress, shippingAddress);

Product product = new Product(getUniqueInt(), getUniqueString(),getUniqueNumber());

Invoice invoice = new Invoice(customer);

IrrelevantInformation

(Obscure Test)

Pattern

Page 28: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

28

55 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Creation Methodpublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5;Address billingAddress = createAnonymousAddress();

Address shippingAddress = createAnonymousAddress();

Customer customer = createCustomer( billingAddress,shippingAddress);

Product product = createAnonymousProduct();

Invoice invoice = new Invoice(customer);

Pattern

56 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Obscure Test - Irrelevant Informationpublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5;

Address billingAddress = createAnonymousAddress();

Address shippingAddress = createAnonymousAddress();

Customer customer = createCustomer(billingAddress, shippingAddress);

Product product = createAnonymousProduct();

Invoice invoice = new Invoice(customer);

// Exercise

invoice.addItemQuantity(product, QUANTITY);

// Verify

LineItem expectedLineItem = newLineItem(invoice,product, QUANTITY, product.getPrice()*QUANTITY );

List lineItems = invoice.getLineItems();

assertEquals("number of items", lineItems.size(), 1);

LineItem actualLineItem = (LineItem)lineItems.get(0);

assertLineItemsEqual(expectedLineItem, actualLineItem);

}

IrrelevantInformation

(Obscure Test)

Code Smell

Page 29: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

29

57 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Remove Irrelevant Informationpublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5 ;

Customer customer = createAnonymousCustomer();`

Product product = createAnonymousProduct();

Invoice invoice = new Invoice(customer);

// Exercise

invoice.addItemQuantity(product, QUANTITY);

// Verify

LineItem expectedLineItem = newLineItem(invoice,product, QUANTITY, product.getPrice()*QUANTITY );

List lineItems = invoice.getLineItems();

assertEquals("number of items", lineItems.size(), 1);

LineItem actualLineItem = (LineItem)lineItems.get(0);

assertLineItemsEqual(expectedLineItem, actualLineItem);}

IrrelevantInformation

(Obscure Test)

Refactoring

58 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Remove Irrelevant Informationpublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5 ;

Product product = createAnonymousProduct();

Invoice invoice = createAnonymousInvoice()

// Exercise

invoice.addItemQuantity(product, QUANTITY);

// Verify

LineItem expectedLineItem = newLineItem(invoice,product, QUANTITY, product.getPrice()*QUANTITY );

List lineItems = invoice.getLineItems();

assertEquals("number of items", lineItems.size(), 1);

LineItem actualLineItem = (LineItem)lineItems.get(0);

assertLineItemsEqual(expectedLineItem, actualLineItem);}

Refactoring

Page 30: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

30

59 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Mechanicshides Intent

Introduce Custom Assertionpublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5 ;

Product product = createAnonymousProduct();

Invoice invoice = createAnonymousInvoice()

// Exercise

invoice.addItemQuantity(product, QUANTITY);

// Verify

LineItem expectedLineItem = newLineItem(invoice,product, QUANTITY, product.getPrice()*QUANTITY );

List lineItems = invoice.getLineItems();

assertEquals("number of items", lineItems.size(), 1);

LineItem actualLineItem = (LineItem)lineItems.get(0);

assertLineItemsEqual(expectedLineItem, actualLineItem);}

Refactoring

60 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Introduce Custom Assertionpublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5 ;

Product product = createAnonymousProduct();

Invoice invoice = createAnonymousInvoice()

// Exercise

invoice.addItemQuantity(product, QUANTITY);

// Verify

LineItem expectedLineItem = newLineItem(invoice,product, QUANTITY, product.getPrice()*QUANTITY );

assertExactlyOneLineItem(invoice, expectedLineItem );

}

Refactoring

Page 31: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

31

61 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

The Whole Test – Donepublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5 ;Product product = createAnonymousProduct();Invoice invoice = createAnonymousInvoice();// Exerciseinvoice.addItemQuantity(product, QUANTITY);// VerifyLineItem expectedLineItem = newLineItem(invoice,

product, QUANTITY, product.getPrice()*QUANTITY );assertExactlyOneLineItem(invoice, expectedLineItem );

}

•Use Domain-Specific Language•Say Only What is Relevant

Given anempty invoice

when I calladdItemQuantity

The invoice will end upwith exactly 1 lineItem

on it.

62 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

The Whole Test – Donepublic void testAddItemQuantity_severalQuantity () {

final int QUANTITY = 5 ;Product product = createAnonymousProduct();Invoice invoice = createAnonymousInvoice();// Wheninvoice.addItemQuantity(product, QUANTITY);// ThenLineItem expectedLineItem = newLineItem(invoice,

product, QUANTITY, product.getPrice()*QUANTITY );assertExactlyOneLineItem(invoice, expectedLineItem );

}

•Use Domain-Specific Language•Say Only What is Relevant

Page 32: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

32

63 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

The Whole Test – Done@Test public voidtestAddItemQuantity_severalQuantity () {

final int QUANTITY = 5 ;Product product = createAnonymousProduct();Invoice invoice = createAnonymousInvoice();// Wheninvoice.addItemQuantity(product, QUANTITY);// ThenLineItem expectedLineItem = newLineItem(invoice,

product, QUANTITY, product.getPrice()*QUANTITY );assertExactlyOneLineItem(invoice, expectedLineItem );

}

•Use Domain-Specific Language•Say Only What is Relevant

64 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

The Whole Test – Done@Test public voidaddItem_severalQuantity_itemValueIsQuantityTimesProductPrice() {

final int QUANTITY = 5 ;Product product = createAnonymousProduct();Invoice invoice = createAnonymousInvoice();// Wheninvoice.addItemQuantity(product, QUANTITY);// ThenLineItem expectedLineItem = newLineItem(invoice,

product, QUANTITY, product.getPrice()*QUANTITY );assertExactlyOneLineItem(invoice, expectedLineItem );

}

•Use Domain-Specific Language•Say Only What is Relevant

Rename

Constantly Strive to Improve Readability

Page 33: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

33

65 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

The Whole Test – Done@Test public voidaddItem_severalQuantity_itemValueIsQuantityTimesProductPrice() {

final int QUANTITY = 5 ;Product product = createAnonymousProduct();Invoice invoice = createAnonymousInvoice();// Wheninvoice.addItemQuantity(product, QUANTITY);// ThenshouldBeExactlyOneLineItemOn(invoice,

expectedLineItem(invoice, product, QUANTITY,product.getPrice()*QUANTITY) );

}

•Use Domain-Specific Language•Say Only What is Relevant

Constantly Strive to Improve Readability

66 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

The Whole Test – Done@Test public voidaddItem_severalQuantity_itemValueIsQuantityTimesProductPrice() {

final int QUANTITY = 5 ;Product product = createIrrelevantProduct();Invoice invoice = createIrrelevantInvoice();// Wheninvoice.addItemQuantity(product, QUANTITY);// ThenshouldBeExactlyOneLineItemOn(invoice,

expectedLineItem(invoice, product, QUANTITY,product.getPrice()*QUANTITY) );

}

•Use Domain-Specific Language•Say Only What is Relevant

Constantly Strive to Improve Readability

Page 34: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

34

67 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

The Whole Test – Done@Test public voidaddItem_severalQuantity_itemValueIsQuantityTimesProductPrice() {

final int QUANTITY = 5 ;Product product = givenAnyProduct();Invoice invoice = givenAnEmptyInvoice();// Wheninvoice.addItemQuantity(product, QUANTITY);// ThenshouldBeExactlyOneLineItemOn(invoice,

expectedLineItem(invoice, product, QUANTITY,product.getPrice()*QUANTITY) );

}

•Use Domain-Specific Language•Say Only What is Relevant

Constantly Strive to Improve Readability

68 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Test CoverageTestInvoiceLineItems {

addItem_singleQuantity_itemValueIsProductPrice…{..}addItem_severalQuantity_itemValueIsQuantityTi… {..}addItem_duplicateProduct_singleItemHasSumOfQ... {..}addItem_differentProduct_oneItemPerProduct() {..}addItem_zeroQuantity_noItem… {..}addItem_severalQuantity_... {..}addItem_discountedPrice_... {..}removeItem_noItemsLeft… {..}removeItem_oneItemLeft… {..}removeItem_ severalItemsLeft… {..}

}

Page 35: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

35

69 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Test CoverageTestInvoiceLineItems {

addItem_singleQuantity_itemValueIsProductPrice…{..}addItem_severalQuantity_itemValueIsQuantityTi… {..}addItem_duplicateProduct_singleItemHasSumOfQ... {..}addItem_differentProduct_oneItemPerProduct() {..}addItem_zeroQuantity_noItem… {..}addItem_severalQuantity_... {..}addItem_discountedPrice_... {..}removeItem_noItemsLeft… {..}removeItem_oneItemLeft… {..}removeItem_ severalItemsLeft… {..}

}

70 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Rapid Test Writing

final int QUANTITY2 = 2 ;

invoice.addItemQuantity(product1, QUANTITY2);

Given anempty invoice

when I calladdItemQuantitytwice with same

product

The invoice will end up withexactly 1 lineItem on it for thesum of the two calls to add..().

@Test public voidaddItem_duplicateProduct_singleItemHasSumOfQuantities () {

final int QUANTITY = 1 ;

Product product1 = givenAnyProduct();

Invoice invoice = givenAnEmptyInvoice();

// When

invoice.addItemQuantity(product1, QUANTITY);

// ThenshouldBeExactlyOneLineItemOn(invoice,

expectedLineItem(invoice, product, QUANTITY,product.getPrice() * QUANTITY) );

}

expectedLineItem(invoice, product, QUANTITY+QUANTITY2,product.getPrice() * (QUANTITY+QUANTITY2) );

GGM53

Page 36: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

Slide 70

GGM53 Redo using new naming conventionsGerard Meszaros, 10/19/2012

Page 37: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

36

71 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Test CoverageTestInvoiceLineItems {

addItem_singleQuantity_itemValueIsProductPrice…{..}addItem_severalQuantity_itemValueIsQuantityTi… {..}addItem_duplicateProduct_singleItemHasSumOfQ...{..}addItem_differentProduct_oneItemPerProduct( ) {..}addItem_zeroQuantity_noItem… {..}addItem_severalQuantity_... {..}addItem_discountedPrice_... {..}removeItem_noItemsLeft… {..}removeItem_oneItemLeft… {..}removeItem_ severalItemsLeft… {..}

}

72 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Rapid Test Writing@Test public void

addItem_differentProduct_oneItemPerProduct () {

final int QUANTITY = 1;

Product product1 = givenAnyProduct();

Invoice invoice = givenAnEmptyInvoice();

// Exercise

invoice.addItemQuantity(product1, QUANTITY);

// VerifyshouldBeExactlyOneLineItemOn(invoice,

expectedLineItem(invoice, product1, QUANTITY,product1.getPrice() * QUANTITY1)

);}

Product product2 = givenAnyProduct();

shouldBeExactlyTwoLineItems(invoice,

invoice.addItemQuantity(product2, QUANTITY2);

when I calladdItemQuantity

twice withdifferent products

expectedLineItem(invoice, product2, QUANTITY2,product2.getPrice() * QUANTITY2 ) );

}

final int QUANTITY2 = 2;

Given anempty invoice

The invoice will end up with 2 lineItems onit, one for each of the two calls to add..().

Page 38: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

37

73 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

@Testpublic void GenerateInvoiceShould…() throws Ex… {

// setup and exercise omitted

Outside-In Development

Hmmm, this is getting ugly!Let’s try another way ….

// verify the actual invoice header matches the expected headerassertNotNull(“Number”, newInvoice.getNumber());assertEquals(“Name”, account. getName(), newInvoice.getName());assertEquals(“Address”, account. getAddr(), newInvoice.getAddr());assertEquals(“City”, account. getC

74 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

@Testpublic void GenerateInvoiceShould…() throws Ex… {

// setup and exercise omittedassertInvoiceHeaderIs( newInvoice , expectedHeader);

}

Outside-In Development

That’s Better!

shouldBeExactlyTwoLineItemsOn(invoice,expectedLineItem( invoice, product1, QUANTITY,

product1.getPrice() * QUANTITY1)expectedLineItem( invoice, product2, QUANTITY2,

product2.getPrice() * QUANTITY2)

);

Now, All I have to do is implementthese test utility methods(test-driven, of course!)

Page 39: Maximizing Expressiveness of Automated Testsxunitpatterns.com/~gerard/craft2014slides.pdf · –Behaviour / Example-Driven Development (B DD / EDD) –Acceptance Test Driven Development

38

75 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Closing Thoughts• Are you automating to find defects or prevent

them?• Are your automated tests good examples?

– Why not? What would you need to change?• Are your tests low maintenance?

– Why not? What causes them to break?– What could you change to make them break less often?– .... to reduce the impact of breakage?

76 Copyright 2014 Gerard Meszaroshttp://craft2014.testAutomationPatterns.com

Thank You!Gerard Meszaros

[email protected]://www.xunitpatterns.com

Slides: http://craft2014.testAutomationPatterns.com

Call me when you:• Want to transition to Agile or Lean• Want to do Agile or Lean better• Want to teach developers how to test• Need help with test automation strategy• Want to improve your test automation

Jolt Productivity Awardwinner - Technical Books

Available on MSDN: