You are on page 1of 28

Unit testing and testability

Unit testing
Are you building it right?
Why?
Dog food
Painful lessons
What is unit testing?
Unit
Test
Types of tests
What to test
Happy flows
Negative scenarios
When to write tests
Test quality ~ expected code lifespan
How
Setup
Exercise
Verify
Teardown
Test doubles
Dummy Object Sitting pretty

Stubs Provide fixed answers


Can answer questions like “how many times was this
Spies called?”

Mocks Makes assertions

Fakes Implement some simpler functionality


Test doubles pitfalls
Abuse Of test doubles
• Testing is cumbersome
• Code is poorly written

Misleading Testing the test double


• Testing the mocked behavior
• Very easy to do or slip by
Principles
Tests showcase their value when they fail. This means...

Good Identify issue fast


names
Small Easy to write
Easy to understand

Fast Quick feedback


Or you’ll feel the pain of the everlasting build 
Testability
Why should I care about testability?
Testability is the ability of a code artefact to run in multiple contexts
Principles
SOLID
Dependency inversion
Single responsibility
Observability
Complexity
Readability
Principles
SOLID
Dependency inversion
Single responsibility
Observability
Complexity
Readability
Principles
SOLID
Dependency inversion
Single responsibility
Observability
Complexity
Readability
Principles
SOLID
Dependency inversion
Single responsibility
Observability
Complexity
Readability
Principles
SOLID
Dependency inversion
Single responsibility
Observability
Complexity
Readability
Principles
SOLID
Dependency inversion
Single responsibility
Observability
Complexity
Readability
How not to write testable code
Let’s look at some piece of code
// special temporary code for homenet - needs improving
if (myslot!=null){
String s=traps(myslot,intentName);
if (s!=null) return s;
}
if (convertUmlauts)
myslot=addUmlauts(myslot);
if (myslot!=null){
q=myslot;//put it in q
// first look at all records
if (myinslots==null)
myinslots=fmanager.getDCXDumpQSlotValues(-1);
FMSDCXDumpQ [] inslots=
myinslots;//fmanager.getDCXDumpQSlotValues(-1);
bestCnt=0;
int index=findSlotInArray(q,inslots);
if (index!=-1){
String button=inslots[index].getQuestion();//.getSlotvalue();
if (!button.equals("")){
button=inslots[index].getQuestion();
}
kbaid=inslots[index].getKbaid();
context="FoundSlot";
fmanager.updateTinkaUserContextEcho(sender, context);
System.out.println("102.XNDF about to run
dotinka:"+context);

return
doTinka(intentName,button,mode,kbaid,dialogPath,"ghome");
}
System.out.println("XNDF not a postback found this
one:"+q+" ::with score:"+bestCnt);
if (q!=null){
String s=traps(q,intentName);
if (s!=null) return s;
}

}
How to write testable code
Let’s look at some piece of code
private Messaging buildChoiceQuickReply(IAmPlusAdapterResponseEvent
iAmPlusAdapterResponseEvent) {
@NonNls
String TALK_TO_TINKA_POSTBACK = ChatbotPostback.TALK_TO_TINKA.name();
@NonNls
String TALK_TO_AN_AGENT_POSTBACK = ChatbotPostback.TALK_TO_AN_AGENT.name();

Map<String, String> resourceBundle = iAmPlusAdapterResponseEvent


.getResourceBundle();

Map<String, String> options = new HashMap<>();


options.put(getAgentQuickReplyLabel(resourceBundle),
TALK_TO_AN_AGENT_POSTBACK);
options.put(getTinkaQuickReplyLabel(resourceBundle),
TALK_TO_TINKA_POSTBACK);

String messageText = resourceBundle


.getOrDefault("handover.message", DEFAULT_HANDOVER_MESSAGE);

String userId = iAmPlusAdapterResponseEvent


.getUser()
.getUserId();
return IamplusMessagingFactory.quickReply(messageText, options, userId);
}
What did you notice?
More meaningful variable names
Cleaner flow
Smaller size
Defaults are more explicit
No useless comments
No commented code
No dangling TODOs
Putting it all together
Workshop time!
Conclusion
Quiz
Summary

You might also like