SlideShare a Scribd company logo
1 of 47
Download to read offline
Unbearable Test Smells
Steven Mak
steven@odd-e.com
www.odd-e.com
twitter: stevenmak
1
Monday, 15 November 2010
Who am I?
2
Name: Steven Mak
Agile Coach at Odd-e
Lives in Hong Kong
Agile/Scrum, TDD Coaching
I love coding - Java, C/C++,
PHP, Perl, C#, VB, and some
weird languages
Monday, 15 November 2010
Copy and Paste Code
Long test codes are copied and pasted somewhere else with only a few
lines changing
3
Monday, 15 November 2010
DRY
Donʼt Repeat Yourself!
Donʼt Repeat Yourself!
Donʼt Repeat Yourself!
Donʼt Repeat Yourself!
Donʼt Repeat Yourself!
Donʼt Repeat Yourself!
Donʼt Repeat Yourself!
Donʼt Repeat Yourself!
4
Monday, 15 November 2010
Not knowing the fixtures
Some initialisation and clean up codes that are repeated in each tests...
5
Monday, 15 November 2010
What is fixture?
TEST_GROUP (TEST_thisObject)
{
void setup() {
}
void teardown() {
}
};
6
Monday, 15 November 2010
Duplication causing fragile
tests
Where is the duplication?
EXPECT_LOG(“ABC error”);
7
Monday, 15 November 2010
Duplication causing fragile
tests
Where is the duplication?
EXPECT_LOG(“ABC error”);
So there is a line in code that
prints this log message
8
Monday, 15 November 2010
Duplication causing fragile
tests
Put it under centralise header file:
#define ABC_ERROR_WITH_EC “ABC error”
The test will then look like:
EXPECT_LOG(ABC_ERROR);
9
Monday, 15 November 2010
Over-Optimism?
Tests that forgot to cover exceptional cases or just covered the easiest
condition
if (aaa() || bbb() || ccc() {
...
} else {
...
}
10
Monday, 15 November 2010
Tests donʼt have assertions
TEST(TEST_GROUP, TEST_THIS)
{
runThisFunctionLaLaLa();
}
11
Monday, 15 November 2010
12
What does it mean by 80% Unit
Test Coverage?
Monday, 15 November 2010
Why xUnits donʼt have
CHECK_NOT_EQUAL?
What is the problem with:
CHECK(TRUE, xxx != 3);
13
Monday, 15 November 2010
Why xUnits donʼt have
CHECK_NOT_EQUAL?
What is the problem with:
CHECK(TRUE, xxx != 3);
Is there any good reason why you
cannot know the output value?
So, tell me what it is then. 14
Monday, 15 November 2010
OK, fine, so I use CHECK with a
specific output value, what now?
What is the problem with:
CHECK(TRUE, xxx == 4);
15
Monday, 15 November 2010
OK, fine, so I use CHECK with a
specific output value, what now?
What is the problem with:
CHECK(TRUE, xxx == 4);
In most xUnits, we have
LONGS_EQUAL telling you the actual
value when it goes wrong instead of a
“false”
16
Monday, 15 November 2010
17
Do you know your xUnit harness?
Monday, 15 November 2010
Further example

 try {

 
 readConfigurationFile();

 
 assertTrue(true);

 } catch (IOException e) {

 
 assertTrue(false);

 
 e.printStackTrace();

 }
These are the places you know your
team does not know the test harness.
18
Monday, 15 November 2010
19
Some xUnit harness
Java: JUnit
.Net: NUnit
C/C++: CppUTest
PHP: PHPUnit
Monday, 15 November 2010
Whatʼs wrong?
What is the problem with:
TEST(TEST_AIH, FAIL_BAD_PARAM)
20
Monday, 15 November 2010
Names donʼt really tell
What is the problem with:
TEST(TEST_AIH, FAIL_BAD_PARAM)
Be more precise about how it
triggered the failure
21
Monday, 15 November 2010
What names tell us?
• Who
- Name of the SUT class
- Name of the method or feature being exercised
• Input
- Important characteristics of any input values
- Anything relevant about the state
• Output
- The outputs expected
- The expected post-exercise state
22
Monday, 15 November 2010
Conditional Test Logic?
// verify Vancouver is in the list
actual = null;
i = flightsFromCalgary.iterator();
while (i.hasNext()) {

 FlightDto flightDto = (FlightDto) i.next();

 if (flightDto.getFlightNumber().equals(

 
 expectedCalgaryToVan.getFlightNumber()))

 {

 
 actual = flightDto;

 
 assertEquals("Flight from Calgary to Vancouver",

 
 
 expectedCalgaryToVan,

 
 
 flightDto);

 
 break;

 }
}
23
Monday, 15 November 2010
Tests that crash 50% of the
time?!!
24
Monday, 15 November 2010
public void testFlightMileage_asKm2() throws Exception {

 // set up fixture

 // exercise constructor

 Flight newFlight = new Flight(validFlightNumber);

 // verify constructed object

 assertEquals(validFlightNumber, newFlight.number);

 assertEquals("", newFlight.airlineCode);

 assertNull(newFlight.airline);

 // set up mileage

 newFlight.setMileage(1122);

 // exercise mileage translator

 int actualKilometres = newFlight.getMileageAsKm();

 // verify results

 int expectedKilometres = 1810;

 assertEquals( expectedKilometres, actualKilometres);

 // now try it with a canceled flight

 newFlight.cancel();

 try {

 
 newFlight.getMileageAsKm();

 
 fail("Expected exception");

 } catch (InvalidRequestException e) {

 
 assertEquals( "Cannot get cancelled flight mileage",

 
 e.getMessage());

 }
}
25
Testing everything at a time
Monday, 15 November 2010
Testing everything at a time
public void testFlightMileage_asKm2() throws Exception {

 // set up fixture

 // exercise constructor

 Flight newFlight = new Flight(validFlightNumber);

 // verify constructed object

 assertEquals(validFlightNumber, newFlight.number);

 assertEquals("", newFlight.airlineCode);

 assertNull(newFlight.airline);

 // set up mileage

 newFlight.setMileage(1122);

 // exercise mileage translator

 int actualKilometres = newFlight.getMileageAsKm();

 // verify results

 int expectedKilometres = 1810;

 assertEquals( expectedKilometres, actualKilometres);

 // now try it with a canceled flight

 newFlight.cancel();

 try {

 
 newFlight.getMileageAsKm();

 
 fail("Expected exception");

 } catch (InvalidRequestException e) {

 
 assertEquals( "Cannot get cancelled flight mileage",

 
 e.getMessage());

 }
}
26
Comments as
deodorant
Monday, 15 November 2010
Testing everything at a time
public void testFlightMileage_asKm2() throws Exception {

 // set up fixture

 // exercise constructor

 Flight newFlight = new Flight(validFlightNumber);

 // verify constructed object

 assertEquals(validFlightNumber, newFlight.number);

 assertEquals("", newFlight.airlineCode);

 assertNull(newFlight.airline);

 // set up mileage

 newFlight.setMileage(1122);

 // exercise mileage translator

 int actualKilometres = newFlight.getMileageAsKm();

 // verify results

 int expectedKilometres = 1810;

 assertEquals( expectedKilometres, actualKilometres);

 // now try it with a canceled flight

 newFlight.cancel();

 try {

 
 newFlight.getMileageAsKm();

 
 fail("Expected exception");

 } catch (InvalidRequestException e) {

 
 assertEquals( "Cannot get cancelled flight mileage",

 
 e.getMessage());

 }
}
27
Duplications with
application logic?
Monday, 15 November 2010
Inappropriate dependencies
• Test setup depending on other tests files
• A test file depending on another test file
• Stub functions depending on other tests
extern int reg_ecx; // in the stub program
int reg_exc; // in SUT
28
Monday, 15 November 2010
What can we do?
29
Monday, 15 November 2010
Try: one test group per file
But why canʼt? is it because of... ?
30
Monday, 15 November 2010
Test initialisation hard to read
and shared among test groups
in the same test file
• Fixtures
• Test Data Builder
• Parameterised Creation
• make-it-easy
31
Monday, 15 November 2010
Dont forget fixtures
TEST_GROUP (TEST_thisObject)
{

 void setup()

 {

 }

 void teardown()

 {

 }
};
32
Monday, 15 November 2010
Test Data Builder
eth_data_buf
->setControl(2)
->withParameterA(3)
->build();
33
Monday, 15 November 2010
Parameterised Creation
@Before
public void setUp() throws Exception {

 alice = new Person();

 alice.setId(1L);

 alice.setFirstname("Alice");

 alice.setLastname("Adams");

 alice.setSsn("111111");

 billy = new Person();

 billy.setId(2L);

 billy.setFirstname("Billy");

 billy.setLastname("Burke");

 billy.setSsn("222222");

 clark = new Person();

 clark.setId(3L);

 clark.setFirstname("Clark");

 clark.setLastname("Cable");

 clark.setSsn("333333");

 alice.isInLoveWith(billy);
}
34
Monday, 15 November 2010
Parameterised Creation
public class ParameterizedCreationMethodExample {

 private Person alice, billy, clark;

 @Before

 public void setUp() throws Exception {

 
 clark = createPerson("Clark", "Cable");

 
 billy = createPerson("Billy", "Burke");

 
 alice = createPerson("Alice", "Adams");

 
 alice.isInLoveWith(billy);

 }

 private Person createPerson(String firstName, String lastName) {

 
 Person person = new Person();

 
 person.setFirstname(firstName);

 
 person.setLastname(lastName);

 
 person.setId(UniqueNumber.next());

 
 person.setSsn(String.valueOf(UniqueNumber.next()));

 
 return person;

 }

 @Test

 public void aliceShouldAcceptWhenProposedToByBilly()

 
 throws Exception {

 
 billy.proposeTo(alice);

 
 assertTrue(alice.isEngagedWith(billy));

 }
}
35
Monday, 15 November 2010
make-it-easy
36
http://code.google.com/p/make-it-easy/
Maker<Apple> appleWith2Leaves = an(Apple, with(2, leaves));
Maker<Apple> ripeApple = appleWith2Leaves.but(with(ripeness, 0.9));
Maker<Apple> unripeApple = appleWith2Leaves.but(with(ripeness, 0.125));
       
Apple apple1 = make(ripeApple);
Apple apple2 = make(unripeApple);
       
Banana defaultBanana = make(a(Banana));
Banana straightBanana = make(a(Banana, with(curve, 0.0)));
Banana squishyBanana = make(a(Banana, with(ripeness, 1.0)));
Monday, 15 November 2010
Try: One assertion per test
37
Monday, 15 November 2010
Customised Assertions
#define CHECK_OBJ(a,b) CHECK_OBJ(a,b, __FILE__,__FILE__)
void CHECK_OBJ(struct* yourObj, struct* myObj, const char* file, int line)
{

 if (structs are not equal) {

 
 SimpleString errorMessage = StringFromFormat(

 
 
 “My struct: %d, %p, %s”, myObj->d, myObj->p, myObj->s);

 
 FAIL_LOCATION(errorMessage.asCharString(), file, line);

 }
}
38
Monday, 15 November 2010
At least: One concept per test
39
Monday, 15 November 2010
Hamcrest
• Framework for writing declarative match criteria
40http://code.google.com/p/hamcrest/
String s = "yes we have no bananas today";
Matcher<String> containsBananas = new StringContains("bananas");
Matcher<String> containsMangoes = new StringContains("mangoes");
assertTrue(containsBananas.matches(s));
assertFalse(containsMangoes.matches(s));
assertThat(s, containsString("bananas"));
assertThat(s, not(containsString("mangoes"));
Or even better
Monday, 15 November 2010
Meaningful Assertion Messages
41
• Donʼt repeat what the built-in test framework
outputs to the console (e.g. name of the test
method)
• Donʼt repeat what the test name explains
• If you donʼt have anything good to say, you donʼt
have to say anything
• Write what should have happened, or what failed
to happen, and possibly mention when it should
have happened
Monday, 15 November 2010
Itʼs Design Smell!!!
42
Monday, 15 November 2010
Extra Constructor
43
public class LogFileMerge {

 private URL logFileA, logFileB;

 public LogFileMerge() {

 
 this(new URL("http://server1/system.log"),

 
 new URL("http://server2/system.log"));

 }

 LogFileMerge(URL a, URL b) {

 
 this.logFileA = a;

 
 this.logFileB = b;

 }
}
Monday, 15 November 2010
Test-Specific SubClass
44
public class CreditCardProcessing {

 public boolean isValid(String cardnumber) {

 
 return validationCodeMatches(cardnumber)

 
 
 && cardIsActive(cardnumber);

 }

 protected boolean validationCodeMatches(String cardnumber) {

 
 // validation logic omitted for brevity...

 }

 protected boolean cardIsActive(String cardnumber) {

 
 // access to merchant system's web service

 
 // omitted for brevity...

 }
}
Monday, 15 November 2010
Still not testable?
45
• Do you follow good design principles?
Monday, 15 November 2010
Thinking
46
Test code is not second class citizen
Good design principles apply:
• Responsibility
• Dependency
• Low Coupling
• High Cohesion
• Indirection
• Protected Variations
Watch out for organisational dysfunction!
Monday, 15 November 2010
References
• Practical TDD and ATDD for Java Developers - Lasse Koskela
• Growing OO Software, guided by tests - Steve Freeman
• xUnit Test Patterns - Gerard Meszaros
47
Steven Mak
steven@odd-e.com
www.odd-e.com
twitter: stevenmak
Monday, 15 November 2010

More Related Content

What's hot

Software Testing - Invited Lecture at UNSW Sydney
Software Testing - Invited Lecture at UNSW SydneySoftware Testing - Invited Lecture at UNSW Sydney
Software Testing - Invited Lecture at UNSW Sydney
julien.ponge
 
G*におけるソフトウェアテスト・シーズンIII
G*におけるソフトウェアテスト・シーズンIIIG*におけるソフトウェアテスト・シーズンIII
G*におけるソフトウェアテスト・シーズンIII
Takuma Watabiki
 

What's hot (20)

Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
 
Software Testing - Invited Lecture at UNSW Sydney
Software Testing - Invited Lecture at UNSW SydneySoftware Testing - Invited Lecture at UNSW Sydney
Software Testing - Invited Lecture at UNSW Sydney
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
 
Proxies are Awesome!
Proxies are Awesome!Proxies are Awesome!
Proxies are Awesome!
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code Generation
 
EcmaScript 6
EcmaScript 6 EcmaScript 6
EcmaScript 6
 
0003 es5 핵심 정리
0003 es5 핵심 정리0003 es5 핵심 정리
0003 es5 핵심 정리
 
Easy Button
Easy ButtonEasy Button
Easy Button
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
TDC2016SP - Trilha .NET
TDC2016SP - Trilha .NETTDC2016SP - Trilha .NET
TDC2016SP - Trilha .NET
 
JavaScript Survival Guide
JavaScript Survival GuideJavaScript Survival Guide
JavaScript Survival Guide
 
G*におけるソフトウェアテスト・シーズンIII
G*におけるソフトウェアテスト・シーズンIIIG*におけるソフトウェアテスト・シーズンIII
G*におけるソフトウェアテスト・シーズンIII
 
Spock Testing Framework - The Next Generation
Spock Testing Framework - The Next GenerationSpock Testing Framework - The Next Generation
Spock Testing Framework - The Next Generation
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS Programmers
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
 
#JavaFX.forReal() - ElsassJUG
#JavaFX.forReal() - ElsassJUG#JavaFX.forReal() - ElsassJUG
#JavaFX.forReal() - ElsassJUG
 
ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
 
ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)
 
ES6 PPT FOR 2016
ES6 PPT FOR 2016ES6 PPT FOR 2016
ES6 PPT FOR 2016
 

Similar to Unbearable Test Code Smell

33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
Tomek Kaczanowski
 
Improving the java type system
Improving the java type systemImproving the java type system
Improving the java type system
João Loff
 
Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bits
Chris Saylor
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
Abed Bukhari
 

Similar to Unbearable Test Code Smell (20)

Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
 
A Test of Strength
A Test of StrengthA Test of Strength
A Test of Strength
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Know
 
Dat testing - An introduction to Java and Android Testing
Dat testing - An introduction to Java and Android TestingDat testing - An introduction to Java and Android Testing
Dat testing - An introduction to Java and Android Testing
 
Imagine a world without mocks
Imagine a world without mocksImagine a world without mocks
Imagine a world without mocks
 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
 
Kotlin Generation
Kotlin GenerationKotlin Generation
Kotlin Generation
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
 
Improving the java type system
Improving the java type systemImproving the java type system
Improving the java type system
 
Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bits
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
 
Writing Good Tests
Writing Good TestsWriting Good Tests
Writing Good Tests
 
Kotlin
KotlinKotlin
Kotlin
 
C# labprograms
C# labprogramsC# labprograms
C# labprograms
 
Cool JVM Tools to Help You Test
Cool JVM Tools to Help You TestCool JVM Tools to Help You Test
Cool JVM Tools to Help You Test
 
Kotlin Overview (PT-BR)
Kotlin Overview (PT-BR)Kotlin Overview (PT-BR)
Kotlin Overview (PT-BR)
 
Google guava
Google guavaGoogle guava
Google guava
 

More from Steven Mak (11)

Continuous Security Testing
Continuous Security TestingContinuous Security Testing
Continuous Security Testing
 
Quality comes free with open source testing tools
Quality comes free with open source testing toolsQuality comes free with open source testing tools
Quality comes free with open source testing tools
 
Adopting technical practices 2013
Adopting technical practices 2013Adopting technical practices 2013
Adopting technical practices 2013
 
100 doors kata solution
100 doors kata solution100 doors kata solution
100 doors kata solution
 
Bossless companies
Bossless companiesBossless companies
Bossless companies
 
Is this how you hate unit testing?
Is this how you hate unit testing?Is this how you hate unit testing?
Is this how you hate unit testing?
 
Driving Quality with TDD
Driving Quality with TDDDriving Quality with TDD
Driving Quality with TDD
 
Sustainable TDD
Sustainable TDDSustainable TDD
Sustainable TDD
 
Introduction to Acceptance Test Driven Development
Introduction to Acceptance Test Driven DevelopmentIntroduction to Acceptance Test Driven Development
Introduction to Acceptance Test Driven Development
 
Essential practices and thinking tools for Agile Adoption
Essential practices and thinking tools for Agile AdoptionEssential practices and thinking tools for Agile Adoption
Essential practices and thinking tools for Agile Adoption
 
ATDD in Practice
ATDD in PracticeATDD in Practice
ATDD in Practice
 

Recently uploaded

怎样办理巴斯大学毕业证(Bath毕业证书)成绩单留信认证
怎样办理巴斯大学毕业证(Bath毕业证书)成绩单留信认证怎样办理巴斯大学毕业证(Bath毕业证书)成绩单留信认证
怎样办理巴斯大学毕业证(Bath毕业证书)成绩单留信认证
eeanqy
 
Resume all my skills and educations and achievement
Resume all my skills and educations and  achievement Resume all my skills and educations and  achievement
Resume all my skills and educations and achievement
210303105569
 
Top profile Call Girls In eluru [ 7014168258 ] Call Me For Genuine Models We ...
Top profile Call Girls In eluru [ 7014168258 ] Call Me For Genuine Models We ...Top profile Call Girls In eluru [ 7014168258 ] Call Me For Genuine Models We ...
Top profile Call Girls In eluru [ 7014168258 ] Call Me For Genuine Models We ...
gajnagarg
 
Top profile Call Girls In Sonipat [ 7014168258 ] Call Me For Genuine Models W...
Top profile Call Girls In Sonipat [ 7014168258 ] Call Me For Genuine Models W...Top profile Call Girls In Sonipat [ 7014168258 ] Call Me For Genuine Models W...
Top profile Call Girls In Sonipat [ 7014168258 ] Call Me For Genuine Models W...
nirzagarg
 
Top profile Call Girls In fatehgarh [ 7014168258 ] Call Me For Genuine Models...
Top profile Call Girls In fatehgarh [ 7014168258 ] Call Me For Genuine Models...Top profile Call Girls In fatehgarh [ 7014168258 ] Call Me For Genuine Models...
Top profile Call Girls In fatehgarh [ 7014168258 ] Call Me For Genuine Models...
gajnagarg
 
Design-System - FinTech - Isadora Agency
Design-System - FinTech - Isadora AgencyDesign-System - FinTech - Isadora Agency
Design-System - FinTech - Isadora Agency
Isadora Agency
 
Q4-Trends-Networks-Module-3.pdfqquater days sheets123456789
Q4-Trends-Networks-Module-3.pdfqquater days sheets123456789Q4-Trends-Networks-Module-3.pdfqquater days sheets123456789
Q4-Trends-Networks-Module-3.pdfqquater days sheets123456789
CristineGraceAcuyan
 
一比一原版(ANU毕业证书)澳大利亚国立大学毕业证原件一模一样
一比一原版(ANU毕业证书)澳大利亚国立大学毕业证原件一模一样一比一原版(ANU毕业证书)澳大利亚国立大学毕业证原件一模一样
一比一原版(ANU毕业证书)澳大利亚国立大学毕业证原件一模一样
yhavx
 
Jual Obat Aborsi Bandung ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan ...
Jual Obat Aborsi Bandung ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan ...Jual Obat Aborsi Bandung ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan ...
Jual Obat Aborsi Bandung ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan ...
ZurliaSoop
 
怎样办理伯明翰大学学院毕业证(Birmingham毕业证书)成绩单留信认证
怎样办理伯明翰大学学院毕业证(Birmingham毕业证书)成绩单留信认证怎样办理伯明翰大学学院毕业证(Birmingham毕业证书)成绩单留信认证
怎样办理伯明翰大学学院毕业证(Birmingham毕业证书)成绩单留信认证
eeanqy
 
一比一原版(WLU毕业证)罗瑞尔大学毕业证成绩单留信学历认证原版一模一样
一比一原版(WLU毕业证)罗瑞尔大学毕业证成绩单留信学历认证原版一模一样一比一原版(WLU毕业证)罗瑞尔大学毕业证成绩单留信学历认证原版一模一样
一比一原版(WLU毕业证)罗瑞尔大学毕业证成绩单留信学历认证原版一模一样
awasv46j
 
Top profile Call Girls In Mysore [ 7014168258 ] Call Me For Genuine Models We...
Top profile Call Girls In Mysore [ 7014168258 ] Call Me For Genuine Models We...Top profile Call Girls In Mysore [ 7014168258 ] Call Me For Genuine Models We...
Top profile Call Girls In Mysore [ 7014168258 ] Call Me For Genuine Models We...
gajnagarg
 

Recently uploaded (20)

LANDSCAPE ARCHITECTURE PORTFOLIO - MAREK MITACEK
LANDSCAPE ARCHITECTURE PORTFOLIO - MAREK MITACEKLANDSCAPE ARCHITECTURE PORTFOLIO - MAREK MITACEK
LANDSCAPE ARCHITECTURE PORTFOLIO - MAREK MITACEK
 
Mohanlalganj ! Call Girls in Lucknow - 450+ Call Girl Cash Payment 9548273370...
Mohanlalganj ! Call Girls in Lucknow - 450+ Call Girl Cash Payment 9548273370...Mohanlalganj ! Call Girls in Lucknow - 450+ Call Girl Cash Payment 9548273370...
Mohanlalganj ! Call Girls in Lucknow - 450+ Call Girl Cash Payment 9548273370...
 
怎样办理巴斯大学毕业证(Bath毕业证书)成绩单留信认证
怎样办理巴斯大学毕业证(Bath毕业证书)成绩单留信认证怎样办理巴斯大学毕业证(Bath毕业证书)成绩单留信认证
怎样办理巴斯大学毕业证(Bath毕业证书)成绩单留信认证
 
Resume all my skills and educations and achievement
Resume all my skills and educations and  achievement Resume all my skills and educations and  achievement
Resume all my skills and educations and achievement
 
Top profile Call Girls In eluru [ 7014168258 ] Call Me For Genuine Models We ...
Top profile Call Girls In eluru [ 7014168258 ] Call Me For Genuine Models We ...Top profile Call Girls In eluru [ 7014168258 ] Call Me For Genuine Models We ...
Top profile Call Girls In eluru [ 7014168258 ] Call Me For Genuine Models We ...
 
Top profile Call Girls In Sonipat [ 7014168258 ] Call Me For Genuine Models W...
Top profile Call Girls In Sonipat [ 7014168258 ] Call Me For Genuine Models W...Top profile Call Girls In Sonipat [ 7014168258 ] Call Me For Genuine Models W...
Top profile Call Girls In Sonipat [ 7014168258 ] Call Me For Genuine Models W...
 
Top profile Call Girls In fatehgarh [ 7014168258 ] Call Me For Genuine Models...
Top profile Call Girls In fatehgarh [ 7014168258 ] Call Me For Genuine Models...Top profile Call Girls In fatehgarh [ 7014168258 ] Call Me For Genuine Models...
Top profile Call Girls In fatehgarh [ 7014168258 ] Call Me For Genuine Models...
 
Eye-Catching Web Design Crafting User Interfaces .docx
Eye-Catching Web Design Crafting User Interfaces .docxEye-Catching Web Design Crafting User Interfaces .docx
Eye-Catching Web Design Crafting User Interfaces .docx
 
Design-System - FinTech - Isadora Agency
Design-System - FinTech - Isadora AgencyDesign-System - FinTech - Isadora Agency
Design-System - FinTech - Isadora Agency
 
Sweety Planet Packaging Design Process Book.pptx
Sweety Planet Packaging Design Process Book.pptxSweety Planet Packaging Design Process Book.pptx
Sweety Planet Packaging Design Process Book.pptx
 
Q4-Trends-Networks-Module-3.pdfqquater days sheets123456789
Q4-Trends-Networks-Module-3.pdfqquater days sheets123456789Q4-Trends-Networks-Module-3.pdfqquater days sheets123456789
Q4-Trends-Networks-Module-3.pdfqquater days sheets123456789
 
The hottest UI and UX Design Trends 2024
The hottest UI and UX Design Trends 2024The hottest UI and UX Design Trends 2024
The hottest UI and UX Design Trends 2024
 
一比一原版(ANU毕业证书)澳大利亚国立大学毕业证原件一模一样
一比一原版(ANU毕业证书)澳大利亚国立大学毕业证原件一模一样一比一原版(ANU毕业证书)澳大利亚国立大学毕业证原件一模一样
一比一原版(ANU毕业证书)澳大利亚国立大学毕业证原件一模一样
 
Jual Obat Aborsi Bandung ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan ...
Jual Obat Aborsi Bandung ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan ...Jual Obat Aborsi Bandung ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan ...
Jual Obat Aborsi Bandung ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan ...
 
怎样办理伯明翰大学学院毕业证(Birmingham毕业证书)成绩单留信认证
怎样办理伯明翰大学学院毕业证(Birmingham毕业证书)成绩单留信认证怎样办理伯明翰大学学院毕业证(Birmingham毕业证书)成绩单留信认证
怎样办理伯明翰大学学院毕业证(Birmingham毕业证书)成绩单留信认证
 
Essential UI/UX Design Principles: A Comprehensive Guide
Essential UI/UX Design Principles: A Comprehensive GuideEssential UI/UX Design Principles: A Comprehensive Guide
Essential UI/UX Design Principles: A Comprehensive Guide
 
一比一原版(WLU毕业证)罗瑞尔大学毕业证成绩单留信学历认证原版一模一样
一比一原版(WLU毕业证)罗瑞尔大学毕业证成绩单留信学历认证原版一模一样一比一原版(WLU毕业证)罗瑞尔大学毕业证成绩单留信学历认证原版一模一样
一比一原版(WLU毕业证)罗瑞尔大学毕业证成绩单留信学历认证原版一模一样
 
Pondicherry Escorts Service Girl ^ 9332606886, WhatsApp Anytime Pondicherry
Pondicherry Escorts Service Girl ^ 9332606886, WhatsApp Anytime PondicherryPondicherry Escorts Service Girl ^ 9332606886, WhatsApp Anytime Pondicherry
Pondicherry Escorts Service Girl ^ 9332606886, WhatsApp Anytime Pondicherry
 
Top profile Call Girls In Mysore [ 7014168258 ] Call Me For Genuine Models We...
Top profile Call Girls In Mysore [ 7014168258 ] Call Me For Genuine Models We...Top profile Call Girls In Mysore [ 7014168258 ] Call Me For Genuine Models We...
Top profile Call Girls In Mysore [ 7014168258 ] Call Me For Genuine Models We...
 
Furniture & Joinery Details_Designs.pptx
Furniture & Joinery Details_Designs.pptxFurniture & Joinery Details_Designs.pptx
Furniture & Joinery Details_Designs.pptx
 

Unbearable Test Code Smell

  • 1. Unbearable Test Smells Steven Mak steven@odd-e.com www.odd-e.com twitter: stevenmak 1 Monday, 15 November 2010
  • 2. Who am I? 2 Name: Steven Mak Agile Coach at Odd-e Lives in Hong Kong Agile/Scrum, TDD Coaching I love coding - Java, C/C++, PHP, Perl, C#, VB, and some weird languages Monday, 15 November 2010
  • 3. Copy and Paste Code Long test codes are copied and pasted somewhere else with only a few lines changing 3 Monday, 15 November 2010
  • 4. DRY Donʼt Repeat Yourself! Donʼt Repeat Yourself! Donʼt Repeat Yourself! Donʼt Repeat Yourself! Donʼt Repeat Yourself! Donʼt Repeat Yourself! Donʼt Repeat Yourself! Donʼt Repeat Yourself! 4 Monday, 15 November 2010
  • 5. Not knowing the fixtures Some initialisation and clean up codes that are repeated in each tests... 5 Monday, 15 November 2010
  • 6. What is fixture? TEST_GROUP (TEST_thisObject) { void setup() { } void teardown() { } }; 6 Monday, 15 November 2010
  • 7. Duplication causing fragile tests Where is the duplication? EXPECT_LOG(“ABC error”); 7 Monday, 15 November 2010
  • 8. Duplication causing fragile tests Where is the duplication? EXPECT_LOG(“ABC error”); So there is a line in code that prints this log message 8 Monday, 15 November 2010
  • 9. Duplication causing fragile tests Put it under centralise header file: #define ABC_ERROR_WITH_EC “ABC error” The test will then look like: EXPECT_LOG(ABC_ERROR); 9 Monday, 15 November 2010
  • 10. Over-Optimism? Tests that forgot to cover exceptional cases or just covered the easiest condition if (aaa() || bbb() || ccc() { ... } else { ... } 10 Monday, 15 November 2010
  • 11. Tests donʼt have assertions TEST(TEST_GROUP, TEST_THIS) { runThisFunctionLaLaLa(); } 11 Monday, 15 November 2010
  • 12. 12 What does it mean by 80% Unit Test Coverage? Monday, 15 November 2010
  • 13. Why xUnits donʼt have CHECK_NOT_EQUAL? What is the problem with: CHECK(TRUE, xxx != 3); 13 Monday, 15 November 2010
  • 14. Why xUnits donʼt have CHECK_NOT_EQUAL? What is the problem with: CHECK(TRUE, xxx != 3); Is there any good reason why you cannot know the output value? So, tell me what it is then. 14 Monday, 15 November 2010
  • 15. OK, fine, so I use CHECK with a specific output value, what now? What is the problem with: CHECK(TRUE, xxx == 4); 15 Monday, 15 November 2010
  • 16. OK, fine, so I use CHECK with a specific output value, what now? What is the problem with: CHECK(TRUE, xxx == 4); In most xUnits, we have LONGS_EQUAL telling you the actual value when it goes wrong instead of a “false” 16 Monday, 15 November 2010
  • 17. 17 Do you know your xUnit harness? Monday, 15 November 2010
  • 18. Further example try { readConfigurationFile(); assertTrue(true); } catch (IOException e) { assertTrue(false); e.printStackTrace(); } These are the places you know your team does not know the test harness. 18 Monday, 15 November 2010
  • 19. 19 Some xUnit harness Java: JUnit .Net: NUnit C/C++: CppUTest PHP: PHPUnit Monday, 15 November 2010
  • 20. Whatʼs wrong? What is the problem with: TEST(TEST_AIH, FAIL_BAD_PARAM) 20 Monday, 15 November 2010
  • 21. Names donʼt really tell What is the problem with: TEST(TEST_AIH, FAIL_BAD_PARAM) Be more precise about how it triggered the failure 21 Monday, 15 November 2010
  • 22. What names tell us? • Who - Name of the SUT class - Name of the method or feature being exercised • Input - Important characteristics of any input values - Anything relevant about the state • Output - The outputs expected - The expected post-exercise state 22 Monday, 15 November 2010
  • 23. Conditional Test Logic? // verify Vancouver is in the list actual = null; i = flightsFromCalgary.iterator(); while (i.hasNext()) { FlightDto flightDto = (FlightDto) i.next(); if (flightDto.getFlightNumber().equals( expectedCalgaryToVan.getFlightNumber())) { actual = flightDto; assertEquals("Flight from Calgary to Vancouver", expectedCalgaryToVan, flightDto); break; } } 23 Monday, 15 November 2010
  • 24. Tests that crash 50% of the time?!! 24 Monday, 15 November 2010
  • 25. public void testFlightMileage_asKm2() throws Exception { // set up fixture // exercise constructor Flight newFlight = new Flight(validFlightNumber); // verify constructed object assertEquals(validFlightNumber, newFlight.number); assertEquals("", newFlight.airlineCode); assertNull(newFlight.airline); // set up mileage newFlight.setMileage(1122); // exercise mileage translator int actualKilometres = newFlight.getMileageAsKm(); // verify results int expectedKilometres = 1810; assertEquals( expectedKilometres, actualKilometres); // now try it with a canceled flight newFlight.cancel(); try { newFlight.getMileageAsKm(); fail("Expected exception"); } catch (InvalidRequestException e) { assertEquals( "Cannot get cancelled flight mileage", e.getMessage()); } } 25 Testing everything at a time Monday, 15 November 2010
  • 26. Testing everything at a time public void testFlightMileage_asKm2() throws Exception { // set up fixture // exercise constructor Flight newFlight = new Flight(validFlightNumber); // verify constructed object assertEquals(validFlightNumber, newFlight.number); assertEquals("", newFlight.airlineCode); assertNull(newFlight.airline); // set up mileage newFlight.setMileage(1122); // exercise mileage translator int actualKilometres = newFlight.getMileageAsKm(); // verify results int expectedKilometres = 1810; assertEquals( expectedKilometres, actualKilometres); // now try it with a canceled flight newFlight.cancel(); try { newFlight.getMileageAsKm(); fail("Expected exception"); } catch (InvalidRequestException e) { assertEquals( "Cannot get cancelled flight mileage", e.getMessage()); } } 26 Comments as deodorant Monday, 15 November 2010
  • 27. Testing everything at a time public void testFlightMileage_asKm2() throws Exception { // set up fixture // exercise constructor Flight newFlight = new Flight(validFlightNumber); // verify constructed object assertEquals(validFlightNumber, newFlight.number); assertEquals("", newFlight.airlineCode); assertNull(newFlight.airline); // set up mileage newFlight.setMileage(1122); // exercise mileage translator int actualKilometres = newFlight.getMileageAsKm(); // verify results int expectedKilometres = 1810; assertEquals( expectedKilometres, actualKilometres); // now try it with a canceled flight newFlight.cancel(); try { newFlight.getMileageAsKm(); fail("Expected exception"); } catch (InvalidRequestException e) { assertEquals( "Cannot get cancelled flight mileage", e.getMessage()); } } 27 Duplications with application logic? Monday, 15 November 2010
  • 28. Inappropriate dependencies • Test setup depending on other tests files • A test file depending on another test file • Stub functions depending on other tests extern int reg_ecx; // in the stub program int reg_exc; // in SUT 28 Monday, 15 November 2010
  • 29. What can we do? 29 Monday, 15 November 2010
  • 30. Try: one test group per file But why canʼt? is it because of... ? 30 Monday, 15 November 2010
  • 31. Test initialisation hard to read and shared among test groups in the same test file • Fixtures • Test Data Builder • Parameterised Creation • make-it-easy 31 Monday, 15 November 2010
  • 32. Dont forget fixtures TEST_GROUP (TEST_thisObject) { void setup() { } void teardown() { } }; 32 Monday, 15 November 2010
  • 34. Parameterised Creation @Before public void setUp() throws Exception { alice = new Person(); alice.setId(1L); alice.setFirstname("Alice"); alice.setLastname("Adams"); alice.setSsn("111111"); billy = new Person(); billy.setId(2L); billy.setFirstname("Billy"); billy.setLastname("Burke"); billy.setSsn("222222"); clark = new Person(); clark.setId(3L); clark.setFirstname("Clark"); clark.setLastname("Cable"); clark.setSsn("333333"); alice.isInLoveWith(billy); } 34 Monday, 15 November 2010
  • 35. Parameterised Creation public class ParameterizedCreationMethodExample { private Person alice, billy, clark; @Before public void setUp() throws Exception { clark = createPerson("Clark", "Cable"); billy = createPerson("Billy", "Burke"); alice = createPerson("Alice", "Adams"); alice.isInLoveWith(billy); } private Person createPerson(String firstName, String lastName) { Person person = new Person(); person.setFirstname(firstName); person.setLastname(lastName); person.setId(UniqueNumber.next()); person.setSsn(String.valueOf(UniqueNumber.next())); return person; } @Test public void aliceShouldAcceptWhenProposedToByBilly() throws Exception { billy.proposeTo(alice); assertTrue(alice.isEngagedWith(billy)); } } 35 Monday, 15 November 2010
  • 36. make-it-easy 36 http://code.google.com/p/make-it-easy/ Maker<Apple> appleWith2Leaves = an(Apple, with(2, leaves)); Maker<Apple> ripeApple = appleWith2Leaves.but(with(ripeness, 0.9)); Maker<Apple> unripeApple = appleWith2Leaves.but(with(ripeness, 0.125));         Apple apple1 = make(ripeApple); Apple apple2 = make(unripeApple);         Banana defaultBanana = make(a(Banana)); Banana straightBanana = make(a(Banana, with(curve, 0.0))); Banana squishyBanana = make(a(Banana, with(ripeness, 1.0))); Monday, 15 November 2010
  • 37. Try: One assertion per test 37 Monday, 15 November 2010
  • 38. Customised Assertions #define CHECK_OBJ(a,b) CHECK_OBJ(a,b, __FILE__,__FILE__) void CHECK_OBJ(struct* yourObj, struct* myObj, const char* file, int line) { if (structs are not equal) { SimpleString errorMessage = StringFromFormat( “My struct: %d, %p, %s”, myObj->d, myObj->p, myObj->s); FAIL_LOCATION(errorMessage.asCharString(), file, line); } } 38 Monday, 15 November 2010
  • 39. At least: One concept per test 39 Monday, 15 November 2010
  • 40. Hamcrest • Framework for writing declarative match criteria 40http://code.google.com/p/hamcrest/ String s = "yes we have no bananas today"; Matcher<String> containsBananas = new StringContains("bananas"); Matcher<String> containsMangoes = new StringContains("mangoes"); assertTrue(containsBananas.matches(s)); assertFalse(containsMangoes.matches(s)); assertThat(s, containsString("bananas")); assertThat(s, not(containsString("mangoes")); Or even better Monday, 15 November 2010
  • 41. Meaningful Assertion Messages 41 • Donʼt repeat what the built-in test framework outputs to the console (e.g. name of the test method) • Donʼt repeat what the test name explains • If you donʼt have anything good to say, you donʼt have to say anything • Write what should have happened, or what failed to happen, and possibly mention when it should have happened Monday, 15 November 2010
  • 43. Extra Constructor 43 public class LogFileMerge { private URL logFileA, logFileB; public LogFileMerge() { this(new URL("http://server1/system.log"), new URL("http://server2/system.log")); } LogFileMerge(URL a, URL b) { this.logFileA = a; this.logFileB = b; } } Monday, 15 November 2010
  • 44. Test-Specific SubClass 44 public class CreditCardProcessing { public boolean isValid(String cardnumber) { return validationCodeMatches(cardnumber) && cardIsActive(cardnumber); } protected boolean validationCodeMatches(String cardnumber) { // validation logic omitted for brevity... } protected boolean cardIsActive(String cardnumber) { // access to merchant system's web service // omitted for brevity... } } Monday, 15 November 2010
  • 45. Still not testable? 45 • Do you follow good design principles? Monday, 15 November 2010
  • 46. Thinking 46 Test code is not second class citizen Good design principles apply: • Responsibility • Dependency • Low Coupling • High Cohesion • Indirection • Protected Variations Watch out for organisational dysfunction! Monday, 15 November 2010
  • 47. References • Practical TDD and ATDD for Java Developers - Lasse Koskela • Growing OO Software, guided by tests - Steve Freeman • xUnit Test Patterns - Gerard Meszaros 47 Steven Mak steven@odd-e.com www.odd-e.com twitter: stevenmak Monday, 15 November 2010