SlideShare a Scribd company logo
1 of 102
Download to read offline
Developer Tests
Things to Know
Vaidas Pilkauskas 2014
Dnipropetrovsk
me
My hobbies
● developer at Wix.com
● main language - Scala
● main professional interest - developer communities
If there is time left after my hobbies
● mountain bicycle rider, snowboarder
● consumer of rock music, contemporary art, etc
me - how to contact me
connect with me on LinkedIn http://lt.linkedin.
com/pub/vaidas-pilkauskas/8/77/863/
add me on G+ https://www.google.com/+VaidasPilkauskas
follow on Twitter @liucijus
“We couldn’t understand why people without technical
knowledge had to tell programmers “what” to do and,
furthermore, they had to supervise “how”
programmers did it.”
Cristian Rennella
http://qz.com/260846/why-our-startup-has-no-bosses-no-office-and-a-four-day-work-week/
What this talk is about
● Things we argue about during code reviews
● Things that took me time to understand and
prove that they are actually good way to go
● Small things we have no time to discuss
during big talks
“Legacy Code is code without
Tests”
Michael Feathers
Working Effectively with Legacy Code
So what is test?
It is system’s exercise under predefined
conditions and then verification of an
expected outcome.
Test structure
http://healthysimulation.com/2743/structure-collapse-simulator-constructed-by-strategic-response-initiatives/
Test phases
Setup
Exercise
Verify
Teardown
Test phases in code
Server server = new NotesServer(); // setup
Note note = new Note("test note"); // setup
Status status = server.add(note); // exercise
assertEquals(SUCCESS, status); // verify
server.shutdown(); // teardown
Start everything in one method
@Test
public void serverShouldAddNoteSuccessfully() {
Server server = new NotesServer(); // setup
Note note = new Note("test note"); // setup
Status status = server.add(note); // exercise
assertEquals(SUCCESS, status); // verify
server.shutdown(); // teardown
}
Refactor to lifecycle methods
@Before public void before() {
server = new NotesServer(); // setup
note = new Note("test note"); // setup
}
@Test public void serverShouldAddNoteSuccessfully() {
Status status = server.add(note); // exercise
assertEquals(SUCCESS, status); // verify
}
@After public void after() {
server.shutdown(); // teardown
}
Rule #1
Do not start from setup/teardown
@Test public void shouldServeEmptyUserList() {
server.start();
assertThat(server.getUsers(), is(empty()));
server.stop();
}
@Before public void startServer() {
server.start();
}
@Test public void shouldServeEmptyUserList() {
//todo: implement
}
@After public void stopServer() {
server.stop();
}
BAD
GOOD
How many colors are there in the
picture?
Source: Josef Albers Interaction of Color
Context matters!
Source: Josef Albers Interaction of Color
Let’s talk about setup in @Before
@Before public void before() {
server = new NotesServer(); // setup
note = new Note("test note"); // setup
}
@Test public void serverShouldAddNoteSuccessfully() {
Status status = server.add(note); // exercise
assertEquals(SUCCESS, status); // verify
}
@After public void after() { server.shutdown(); // teardown }
http://www.worldwildlife.org/threats/pollution
Setup pollution
Setup pollution - #1
● Every line in setup must be relevant to all tests.
BAD
@Before public void preparePets() {
cat = new Cat(); // only needed by dogShouldSayFoo
dog = new Dog(); // only needed by catShouldSayBar
}
@Test public void dogShouldSayFoo() {
assertThat(dog.says(), is("foo"))
}
@Test public void catShouldSayBar() {
assertThat(cat.says(), is("bar"))
}
Setup pollution - #2
● It is tempting to add additional setup tuning just to
fix/enhance one test.
BAD
@Before public void preparePets() {
cat = new Cat().withHairstyle(CURLY);
dog = new Dog();
}
@Test public void curlyCatShouldFeelBeautiful(){
assertThat(cat.isFeelingBeautiful(), is(true));
}
@Test public void dogShouldSayFoo() {
assertThat(dog.says(), is("foo"));
}
@Test public void catShouldSayBar() {
assertThat(cat.says(), is("bar"));
}
Setup pollution - #3
● Rich setup makes tests slow!
Setup pollution - #4
● Setup is to bootstrap your SUT.
Setup pollution - #5
● Setup hides details! Do not hide test preconditions.
Setting up note inside test method
@Before public void before() {
server = new NotesServer(); // setup
}
@Test public void serverShouldAddNoteSuccessfully() {
note = new Note("test note"); // setup
Status status = server.add(note); // exercise
assertEquals(SUCCESS, status); // verify
}
But then be more specific
@Test
public void serverShouldAddSingleLineNoteSuccesfully() {
// * set up which is actual for the current method
// * use scope specific name
Note singleLineNote = new Note("test note"); // setup
Status status = server.add(singleLineNote); // exercise
assertEquals(SUCCESS, status); // verify
}
Give good names to setup methods
@Before public void createNotesServer() {
server = new NotesServer();
}
Summary of test code organization
● DRY principle.
● Readability. BDD vs. DRY
● Consistency. Maintain the same style across
your codebase.
● Complexity. It may dictate the way you go.
Refactoring
Refactoring is about improving the design of
existing code. It is the process of changing a
software system in such a way that it does not
alter the external behavior of the code, yet
improves its internal structure.
Martin Fowler
Refactoring: Improving the Design of Existing Code
What do we test?
http://www.dumpaday.com/random-pictures/daily-randomness-40-pics/
Test behaviour not methods
@Test public void testGetBalance() {
assertEquals(0, account.getBalance())
}
@Test
public void shouldBeEmptyAfterCreation() {
assertEquals(0, account.getBalance());
}
Test behaviour not methods
● Think of a contract
Test behaviour not methods
● Think of a contract
● And responsibilities
Test behaviour not methods
● Think of a contract
● And responsibilities
● Specify requirements as tests
Test behaviour not methods
● Think of a contract
● And responsibilities
● Specify requirements as tests
● Happens naturally when done in test-first
approach
Matchers
http://www.allthatiknow.com/2013/10/comparing-google-analytics-standard-vs-premium/
Matchers
● Assert on the right level of abstraction
● Encapsulate testing logic
Matcher libraries
● Hamcrest - standard matcher lib for JUnit
● AssertJ - fluent assertions (IDE friendly)
● Provide common matchers
● You can write your own custom matchers
Hamcrest
assertThat(frodo.getName(), equalTo("Frodo"));
assertThat(frodo.getName(), is(equalTo("Frodo")));
assertThat(frodo.getName(), is("Frodo"));
//JUnit
assertEquals("Frodo", frodo.getName())
AssertJ
assertThat(frodo.getName()).isEqualTo("Frodo");
assertThat(frodo).isNotEqualTo(sauron).isIn(fellowshipOfTheRing);
assertThat(sauron).isNotIn(fellowshipOfTheRing);
//JUnit
assertEquals("Frodo", frodo.getName())
Custom matchers
http://mimiandeunice.com/2011/04/19/compare/
Custom matchers
Are matchers that we write specifically for our
projects.
Custom matchers
● Help communicate test intention
● Abstract assertion logic
Custom matchers
● Help communicate test intention
● Abstract assertion logic
● Are reusable and save time in large projects
● You may have a custom message to be
more specific about test failure
Custom matchers
@Test
public void shouldHaveIsbnGenerated() {
Book book = new Book(1l, "5555", "A book");
assertThat(book, hasIsbn("1234"));
}
Failing a test
fail()
In some cases (e.g. testing exceptions) you
may want to force test to fail if some expected
situation does not happen
fail()
try {
// do stuff...
fail("Exception not thrown");
} catch(Exception e){
assertTrue(e.hasSomeFlag());
}
fail()
● Fundamentally not bad, but better use
matchers for expected failure
● Matchers help to clarify test intention
● Don’t forget - expected behaviour is an
opposite of a failing test
Anti-pattern: The Ugly Mirror
http://www.iwillnotdiet.com/?attachment_id=2605
Anti-pattern: The Ugly Mirror
@Test
public void personToStringShouldIncludeNameAndSurname() {
Person person = new Person("Волк", "Серый");
String expected =
"Person[" + person.getName() + " " + person.getSurname() + "]"
assertEquals(expected, person.toString());
}
Anti-pattern: The Ugly Mirror
@Test
public void personToStringShouldIncludeNameAndSurname() {
Person person = new Person("Волк", "Серый");
String expected =
"Person[" + person.getName() + " " + person.getSurname() + "]"
assertEquals(expected, person.toString());
}
Anti-pattern: The Ugly Mirror
@Test
public void personToStringShouldIncludeNameAndSurname() {
Person person = new Person("Волк", "Серый");
assertEquals("Person[Волк Серый]", person.toString());
}
How to turn off the test?
http://namo-rekonstrukcija.blogspot.com/2013/05/elektra-izeminimas.html
Why would you want to turn off the
test?
Why would you want to turn off the
test?
Well, because it fails… :)
Ignoring tests
● Always use ignore/pending API from your
test library (JUnit @Ignore)
@Ignore("charge simplicator not ready")
@Test public void shouldChargeMonthly() {
//implementation which fails
}
Ignoring tests
● Do not comment out or false assert your test
//Will fix it later™
//@Test public void shouldBeZeroInitialy() {
// assertEquals(0, account.getBalance());
//}
@Test public void shouldBeZeroInitialy() {
assertEquals(1, account.getBalance());
}
Ignoring tests
● Do not comment out or false assert your test
//Will fix it later™
//@Test public void shouldBeZeroInitialy() {
// assertEquals(0, account.getBalance());
//}
@Test public void shouldBeZeroInitialy() {
assertEquals(1, account.getBalance());
}
Who is Will?
Ignoring tests
● If you do not need a test - delete it
What to do with exceptions?
http://s273.photobucket.com/user/eliteskater08/media/meateatingrabbit.jpg.html
Exceptions
● If you can, use matchers instead of
○ @Test(expected=?)
○ try-catch approach
JUnit expected exception
@Test(expected=IndexOutOfBoundsException.class)
public void shouldThrowIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
//matcher in Specs2 (Scala)
server.process(None) must throwA[NothingToProccess]
try and catch
public void shouldThrowIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
try {
Object o = emptyList.get(0);
fail("Should throw IndexOutOfBoundsException");
} catch(IndexOutOfBoundsException e)){
//consider asserting message!
}
}
Exceptions
● catch-exception lib
catch-exception lib
List myList = new ArrayList();
catchException(myList).get(1);
assertThat(caughtException(),
allOf(
is(IndexOutOfBoundsException.class),
hasMessage("Index: 1, Size: 0"),
hasNoCause()
)
);
Exceptions
● What about ExpectedException Rule?
○ My personal opinion - not that intuitive
○ breaks arrange/act/assert flow
ExpectedException rule
@Rule public ExpectedException exception = ExpectedException.none();
@Test
public void testExpectedException() {
exception.expect(IllegalArgumentException.class);
exception.expectMessage(containsString('Invalid age'));
new Person('Vilkas', -1);
}
//Person constructor
public Person(String name, int age) {
if (age <= 0) throw new IllegalArgumentException('Invalid age:' + age);
// ...
}
Testing with time
http://wisconsinrelocation.net/post/1295775/tickle-your-funny-bone-----time-management-is-everything--
Problem
public class MyService {
...
public void process(LocalDate date) {
if (date.isBefore(LocalDate.now()) {
...
} else {
...
}
}
}
Testing with Time
● Design your system where time is a
collaborator
● Inject test specific time provider in your test
○ constant time
○ slow time
○ boundary cases time
Control time with Clock
public class MyService {
private Clock clock; // dependency inject
...
public void process(LocalDate date) {
if (date.isBefore(LocalDate.now(clock)) {
...
} else {
...
}
}
}
Collectionshttp://mycoolguitars.com/cool-guitar-collections/
Collections - multiple properties to
assert
● Is null?
● Size
● Order
● Content
Collections
● Most of the time you want to assert on collection content
assertThat(users, containsInAnyOrder("andrius", "vaidas"))
Collections
● Prefer exact content matching
assertThat(users, contains("andrius", "vaidas"))
Collections
● Avoid incomplete assertions
//users=List.of("andrius", "vaidas", "valdemaras", "jonas")
assertThat(users, hasItems("andrius", "vaidas"))
Collections
● Do not sort just because it is easier to assert!
assertThat(sort(users), contains("andrius", "vaidas"))
Collections
● Multiple assertions are worse than single content
assertion
assertThat(users, hasSize(2))
assertThat(users, hasItems("andrius", "vaidas"))
Collections
● Use matchers!
Random values
Random values in tests
● Most of the time you do not want it
@Test public void shouldStartWithFirst() {
String a = randomString();
String b = randomString();
assertThat(a + b, startsWith(a));
}
Random values in tests
● Unless you depend on randomness a lot (eg.
password generation*)
*Thanks to Aleksandar Tomovski for a good example
Random values in tests
● Use property based testing (which is also
hard)
//example from ScalaCheck
property("startsWith") = forAll { (a: String, b: String) =>
(a+b).startsWith(a)
}
Random values in tests
● Do not make dummy values random
cat = new Cat(randomString());
cat = new Cat("dummyName");
What if we still need random cases?
Generate Multiple Test Cases
● Quality over quantity
Generate Multiple Test Cases
● Quality over quantity
● Think of boundary cases, that you may want
to detect with random test
Generate Multiple Test Cases
● Quality over quantity
● Think of boundary cases, that you may want
to detect with random test
● Use parameterized tests
Generate Multiple Test Cases
● Quality over quantity
● Think of boundary cases, that you may want
to detect with random test
● Use parameterized tests
● Random is hard to repeat
Generate Multiple Test Cases
● Quality over quantity
● Think of boundary cases, that you may want
to detect with random test
● Use parameterized tests
● Random is hard to repeat
● Flickering tests
How many assertions per test?
http://dailypicksandflicks.com/2012/05/11/daily-picdump-455/4-beers-at-the-same-time/
How many assertions per test?
● Unit test - one assertion per test. Must be
clear and readable
● Proper tests should fail for exactly one
reason
● End to end - best case one assertion per
test, but more are allowed
● Consider custom matchers
How many assertions per test?
● Unit test - one assertion per test. Must be
clear and readable
● Proper tests should fail for exactly one
reason
● End to end - best case one assertion per
test, but more are allowed
● Consider custom matchers
Thing #13
Decoupling in End-to-end tests
What can be better in this test?
[pseudocode]
@Test shouldRetrieveUserByLogin() {
String userJson = "{"username": "vaidas"}";
HttpRequest post = new Post("https://localhost:8080/users", userJson);
HttpResponse postResp = HttpClient().execute(post);
assertThat(postResp.status, is(200));
HttpRequest get = new Get("https://localhost:8080/users/vaidas");
HttpResponse getResp = HttpClient().execute(get);
User user = mapper.readValue(getResp, User.class);
assertThat(user.username, is("vaidas"));
}
What can be better in this test?
[pseudocode]
@Test shouldRetrieveUserByLogin() {
String userJson = "{"username": "vaidas"}";
HttpRequest post = new Post("https://localhost:8080/users", userJson);
HttpResponse postResp = HttpClient().execute(post);
assertThat(postResp.status, is( 200));
HttpRequest get = new Get("https://localhost:8080/users/vaidas");
HttpResponse getResp = HttpClient().execute(get);
User user = mapper.readValue(getResp, User.class);
assertThat(user.username, is("vaidas"));
}
Decoupling from low level details
[pseudocode]
@Test shouldRetrieveUserByUsername() {
CreateUserResponse createResp = aCreateUserRequest().withUsername("vaidas").execute();
assertThat(createResp, isSuccessful());
GetUserResponse getResp = aGetUserRequest().withUsername("vaidas").execute();
assertThat(getResp, allOf(isSuccessful(), hasUsername("vaidas")));
}
Summary
● Context matters
● Testings is controversial topic
● And very opinionated
Thanks!
Q & A

More Related Content

What's hot

Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testingjeresig
 
Webdriver cheatsheets summary
Webdriver cheatsheets summaryWebdriver cheatsheets summary
Webdriver cheatsheets summaryAlan Richardson
 
Develop Maintainable Apps
Develop Maintainable AppsDevelop Maintainable Apps
Develop Maintainable AppsAnnyce Davis
 
iOS Unit Testing
iOS Unit TestingiOS Unit Testing
iOS Unit Testingsgleadow
 
Creating Gradle Plugins
Creating Gradle PluginsCreating Gradle Plugins
Creating Gradle PluginsAnnyce Davis
 
Testing React Applications
Testing React ApplicationsTesting React Applications
Testing React Applicationsstbaechler
 
Real World Selenium Testing
Real World Selenium TestingReal World Selenium Testing
Real World Selenium TestingMary Jo Sminkey
 
"How keep normal blood pressure using TDD" By Roman Loparev
"How keep normal blood pressure using TDD" By Roman Loparev"How keep normal blood pressure using TDD" By Roman Loparev
"How keep normal blood pressure using TDD" By Roman LoparevCiklum Ukraine
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Howsatesgoral
 
Not your father's tests
Not your father's testsNot your father's tests
Not your father's testsSean P. Floyd
 
Test Driven Development With YUI Test (Ajax Experience 2008)
Test Driven Development With YUI Test (Ajax Experience 2008)Test Driven Development With YUI Test (Ajax Experience 2008)
Test Driven Development With YUI Test (Ajax Experience 2008)Nicholas Zakas
 
Token Testing Slides
Token  Testing SlidesToken  Testing Slides
Token Testing Slidesericholscher
 
Isomorphic React Apps Testing
Isomorphic React Apps TestingIsomorphic React Apps Testing
Isomorphic React Apps TestingMikhail Larchanka
 
Extracting Plugins And Gems From Rails Apps
Extracting Plugins And Gems From Rails AppsExtracting Plugins And Gems From Rails Apps
Extracting Plugins And Gems From Rails AppsJosh Nichols
 
Creating Gradle Plugins - GR8Conf US
Creating Gradle Plugins - GR8Conf USCreating Gradle Plugins - GR8Conf US
Creating Gradle Plugins - GR8Conf USAnnyce Davis
 

What's hot (20)

Your code are my tests
Your code are my testsYour code are my tests
Your code are my tests
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testing
 
Webdriver cheatsheets summary
Webdriver cheatsheets summaryWebdriver cheatsheets summary
Webdriver cheatsheets summary
 
Develop Maintainable Apps
Develop Maintainable AppsDevelop Maintainable Apps
Develop Maintainable Apps
 
iOS Unit Testing
iOS Unit TestingiOS Unit Testing
iOS Unit Testing
 
Creating Gradle Plugins
Creating Gradle PluginsCreating Gradle Plugins
Creating Gradle Plugins
 
Agile Swift
Agile SwiftAgile Swift
Agile Swift
 
Testing React Applications
Testing React ApplicationsTesting React Applications
Testing React Applications
 
Real World Selenium Testing
Real World Selenium TestingReal World Selenium Testing
Real World Selenium Testing
 
Clean tests good tests
Clean tests   good testsClean tests   good tests
Clean tests good tests
 
"How keep normal blood pressure using TDD" By Roman Loparev
"How keep normal blood pressure using TDD" By Roman Loparev"How keep normal blood pressure using TDD" By Roman Loparev
"How keep normal blood pressure using TDD" By Roman Loparev
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Hows
 
Not your father's tests
Not your father's testsNot your father's tests
Not your father's tests
 
Test Driven Development With YUI Test (Ajax Experience 2008)
Test Driven Development With YUI Test (Ajax Experience 2008)Test Driven Development With YUI Test (Ajax Experience 2008)
Test Driven Development With YUI Test (Ajax Experience 2008)
 
Agile Android
Agile AndroidAgile Android
Agile Android
 
Unit Testing in iOS
Unit Testing in iOSUnit Testing in iOS
Unit Testing in iOS
 
Token Testing Slides
Token  Testing SlidesToken  Testing Slides
Token Testing Slides
 
Isomorphic React Apps Testing
Isomorphic React Apps TestingIsomorphic React Apps Testing
Isomorphic React Apps Testing
 
Extracting Plugins And Gems From Rails Apps
Extracting Plugins And Gems From Rails AppsExtracting Plugins And Gems From Rails Apps
Extracting Plugins And Gems From Rails Apps
 
Creating Gradle Plugins - GR8Conf US
Creating Gradle Plugins - GR8Conf USCreating Gradle Plugins - GR8Conf US
Creating Gradle Plugins - GR8Conf US
 

Similar to Developer Tests - Things to Know

Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Knowvilniusjug
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETBen Hall
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - GreachHamletDRC
 
6 Traits of a Successful Test Automation Architecture
6 Traits of a Successful Test Automation Architecture6 Traits of a Successful Test Automation Architecture
6 Traits of a Successful Test Automation ArchitectureErdem YILDIRIM
 
Testing and validating spark programs - Strata SJ 2016
Testing and validating spark programs - Strata SJ 2016Testing and validating spark programs - Strata SJ 2016
Testing and validating spark programs - Strata SJ 2016Holden Karau
 
Testing and validating distributed systems with Apache Spark and Apache Beam ...
Testing and validating distributed systems with Apache Spark and Apache Beam ...Testing and validating distributed systems with Apache Spark and Apache Beam ...
Testing and validating distributed systems with Apache Spark and Apache Beam ...Holden Karau
 
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017Ortus Solutions, Corp
 
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF SummitOrtus Solutions, Corp
 
How do I write testable javascript?
How do I write testable javascript?How do I write testable javascript?
How do I write testable javascript?devObjective
 
Testing with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs LifeTesting with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs LifePeter Gfader
 
Pragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptPragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptdavejohnson
 
Automated Frontend Testing
Automated Frontend TestingAutomated Frontend Testing
Automated Frontend TestingNeil Crosby
 
2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratiehcderaad
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyDavid Padbury
 
Beyond TDD: Enabling Your Team to Continuously Deliver Software
Beyond TDD: Enabling Your Team to Continuously Deliver SoftwareBeyond TDD: Enabling Your Team to Continuously Deliver Software
Beyond TDD: Enabling Your Team to Continuously Deliver SoftwareChris Weldon
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e bigAndy Peterson
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiRan Mizrahi
 
Joomla! Day Chicago 2011 Presentation - Steven Pignataro
Joomla! Day Chicago 2011 Presentation - Steven PignataroJoomla! Day Chicago 2011 Presentation - Steven Pignataro
Joomla! Day Chicago 2011 Presentation - Steven PignataroSteven Pignataro
 

Similar to Developer Tests - Things to Know (20)

Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Know
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NET
 
How to write Testable Javascript
How to write Testable JavascriptHow to write Testable Javascript
How to write Testable Javascript
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - Greach
 
6 Traits of a Successful Test Automation Architecture
6 Traits of a Successful Test Automation Architecture6 Traits of a Successful Test Automation Architecture
6 Traits of a Successful Test Automation Architecture
 
Testing and validating spark programs - Strata SJ 2016
Testing and validating spark programs - Strata SJ 2016Testing and validating spark programs - Strata SJ 2016
Testing and validating spark programs - Strata SJ 2016
 
Testing and validating distributed systems with Apache Spark and Apache Beam ...
Testing and validating distributed systems with Apache Spark and Apache Beam ...Testing and validating distributed systems with Apache Spark and Apache Beam ...
Testing and validating distributed systems with Apache Spark and Apache Beam ...
 
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
 
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
3 Ways to test your ColdFusion API - 2017 Adobe CF Summit
 
How do I write testable javascript?
How do I write testable javascript?How do I write testable javascript?
How do I write testable javascript?
 
Testing with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs LifeTesting with VS2010 - A Bugs Life
Testing with VS2010 - A Bugs Life
 
Pragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptPragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScript
 
Automated Frontend Testing
Automated Frontend TestingAutomated Frontend Testing
Automated Frontend Testing
 
2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie2014 11 20 Drupal 7 -> 8 test migratie
2014 11 20 Drupal 7 -> 8 test migratie
 
HTML5 for the Silverlight Guy
HTML5 for the Silverlight GuyHTML5 for the Silverlight Guy
HTML5 for the Silverlight Guy
 
Beyond TDD: Enabling Your Team to Continuously Deliver Software
Beyond TDD: Enabling Your Team to Continuously Deliver SoftwareBeyond TDD: Enabling Your Team to Continuously Deliver Software
Beyond TDD: Enabling Your Team to Continuously Deliver Software
 
Ansible testing
Ansible   testingAnsible   testing
Ansible testing
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e big
 
Intro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran MizrahiIntro To JavaScript Unit Testing - Ran Mizrahi
Intro To JavaScript Unit Testing - Ran Mizrahi
 
Joomla! Day Chicago 2011 Presentation - Steven Pignataro
Joomla! Day Chicago 2011 Presentation - Steven PignataroJoomla! Day Chicago 2011 Presentation - Steven Pignataro
Joomla! Day Chicago 2011 Presentation - Steven Pignataro
 

More from Vaidas Pilkauskas

Can You Trust Your Tests? (Agile Tour 2015 Kaunas)
Can You Trust Your Tests? (Agile Tour 2015 Kaunas)Can You Trust Your Tests? (Agile Tour 2015 Kaunas)
Can You Trust Your Tests? (Agile Tour 2015 Kaunas)Vaidas Pilkauskas
 

More from Vaidas Pilkauskas (6)

Hiring Backend Engineers
Hiring Backend EngineersHiring Backend Engineers
Hiring Backend Engineers
 
Understanding Mocks
Understanding MocksUnderstanding Mocks
Understanding Mocks
 
Coderetreat introduction
Coderetreat introductionCoderetreat introduction
Coderetreat introduction
 
My Test Automation Journey
My Test Automation JourneyMy Test Automation Journey
My Test Automation Journey
 
Can You Trust Your Tests? (Agile Tour 2015 Kaunas)
Can You Trust Your Tests? (Agile Tour 2015 Kaunas)Can You Trust Your Tests? (Agile Tour 2015 Kaunas)
Can You Trust Your Tests? (Agile Tour 2015 Kaunas)
 
Can you trust your tests?
Can you trust your tests?Can you trust your tests?
Can you trust your tests?
 

Recently uploaded

Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 

Recently uploaded (20)

Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 

Developer Tests - Things to Know

  • 1. Developer Tests Things to Know Vaidas Pilkauskas 2014 Dnipropetrovsk
  • 2. me My hobbies ● developer at Wix.com ● main language - Scala ● main professional interest - developer communities If there is time left after my hobbies ● mountain bicycle rider, snowboarder ● consumer of rock music, contemporary art, etc
  • 3. me - how to contact me connect with me on LinkedIn http://lt.linkedin. com/pub/vaidas-pilkauskas/8/77/863/ add me on G+ https://www.google.com/+VaidasPilkauskas follow on Twitter @liucijus
  • 4. “We couldn’t understand why people without technical knowledge had to tell programmers “what” to do and, furthermore, they had to supervise “how” programmers did it.” Cristian Rennella http://qz.com/260846/why-our-startup-has-no-bosses-no-office-and-a-four-day-work-week/
  • 5. What this talk is about ● Things we argue about during code reviews ● Things that took me time to understand and prove that they are actually good way to go ● Small things we have no time to discuss during big talks
  • 6.
  • 7. “Legacy Code is code without Tests” Michael Feathers Working Effectively with Legacy Code
  • 8. So what is test? It is system’s exercise under predefined conditions and then verification of an expected outcome.
  • 11. Test phases in code Server server = new NotesServer(); // setup Note note = new Note("test note"); // setup Status status = server.add(note); // exercise assertEquals(SUCCESS, status); // verify server.shutdown(); // teardown
  • 12. Start everything in one method @Test public void serverShouldAddNoteSuccessfully() { Server server = new NotesServer(); // setup Note note = new Note("test note"); // setup Status status = server.add(note); // exercise assertEquals(SUCCESS, status); // verify server.shutdown(); // teardown }
  • 13. Refactor to lifecycle methods @Before public void before() { server = new NotesServer(); // setup note = new Note("test note"); // setup } @Test public void serverShouldAddNoteSuccessfully() { Status status = server.add(note); // exercise assertEquals(SUCCESS, status); // verify } @After public void after() { server.shutdown(); // teardown }
  • 14. Rule #1 Do not start from setup/teardown
  • 15. @Test public void shouldServeEmptyUserList() { server.start(); assertThat(server.getUsers(), is(empty())); server.stop(); } @Before public void startServer() { server.start(); } @Test public void shouldServeEmptyUserList() { //todo: implement } @After public void stopServer() { server.stop(); } BAD GOOD
  • 16. How many colors are there in the picture? Source: Josef Albers Interaction of Color
  • 17. Context matters! Source: Josef Albers Interaction of Color
  • 18. Let’s talk about setup in @Before @Before public void before() { server = new NotesServer(); // setup note = new Note("test note"); // setup } @Test public void serverShouldAddNoteSuccessfully() { Status status = server.add(note); // exercise assertEquals(SUCCESS, status); // verify } @After public void after() { server.shutdown(); // teardown }
  • 20. Setup pollution - #1 ● Every line in setup must be relevant to all tests.
  • 21. BAD @Before public void preparePets() { cat = new Cat(); // only needed by dogShouldSayFoo dog = new Dog(); // only needed by catShouldSayBar } @Test public void dogShouldSayFoo() { assertThat(dog.says(), is("foo")) } @Test public void catShouldSayBar() { assertThat(cat.says(), is("bar")) }
  • 22. Setup pollution - #2 ● It is tempting to add additional setup tuning just to fix/enhance one test.
  • 23. BAD @Before public void preparePets() { cat = new Cat().withHairstyle(CURLY); dog = new Dog(); } @Test public void curlyCatShouldFeelBeautiful(){ assertThat(cat.isFeelingBeautiful(), is(true)); } @Test public void dogShouldSayFoo() { assertThat(dog.says(), is("foo")); } @Test public void catShouldSayBar() { assertThat(cat.says(), is("bar")); }
  • 24. Setup pollution - #3 ● Rich setup makes tests slow!
  • 25. Setup pollution - #4 ● Setup is to bootstrap your SUT.
  • 26. Setup pollution - #5 ● Setup hides details! Do not hide test preconditions.
  • 27. Setting up note inside test method @Before public void before() { server = new NotesServer(); // setup } @Test public void serverShouldAddNoteSuccessfully() { note = new Note("test note"); // setup Status status = server.add(note); // exercise assertEquals(SUCCESS, status); // verify }
  • 28. But then be more specific @Test public void serverShouldAddSingleLineNoteSuccesfully() { // * set up which is actual for the current method // * use scope specific name Note singleLineNote = new Note("test note"); // setup Status status = server.add(singleLineNote); // exercise assertEquals(SUCCESS, status); // verify }
  • 29. Give good names to setup methods @Before public void createNotesServer() { server = new NotesServer(); }
  • 30. Summary of test code organization ● DRY principle. ● Readability. BDD vs. DRY ● Consistency. Maintain the same style across your codebase. ● Complexity. It may dictate the way you go.
  • 31. Refactoring Refactoring is about improving the design of existing code. It is the process of changing a software system in such a way that it does not alter the external behavior of the code, yet improves its internal structure. Martin Fowler Refactoring: Improving the Design of Existing Code
  • 32. What do we test? http://www.dumpaday.com/random-pictures/daily-randomness-40-pics/
  • 33. Test behaviour not methods @Test public void testGetBalance() { assertEquals(0, account.getBalance()) } @Test public void shouldBeEmptyAfterCreation() { assertEquals(0, account.getBalance()); }
  • 34. Test behaviour not methods ● Think of a contract
  • 35. Test behaviour not methods ● Think of a contract ● And responsibilities
  • 36. Test behaviour not methods ● Think of a contract ● And responsibilities ● Specify requirements as tests
  • 37. Test behaviour not methods ● Think of a contract ● And responsibilities ● Specify requirements as tests ● Happens naturally when done in test-first approach
  • 39. Matchers ● Assert on the right level of abstraction ● Encapsulate testing logic
  • 40. Matcher libraries ● Hamcrest - standard matcher lib for JUnit ● AssertJ - fluent assertions (IDE friendly) ● Provide common matchers ● You can write your own custom matchers
  • 44. Custom matchers Are matchers that we write specifically for our projects.
  • 45. Custom matchers ● Help communicate test intention ● Abstract assertion logic
  • 46. Custom matchers ● Help communicate test intention ● Abstract assertion logic ● Are reusable and save time in large projects ● You may have a custom message to be more specific about test failure
  • 47. Custom matchers @Test public void shouldHaveIsbnGenerated() { Book book = new Book(1l, "5555", "A book"); assertThat(book, hasIsbn("1234")); }
  • 49. fail() In some cases (e.g. testing exceptions) you may want to force test to fail if some expected situation does not happen
  • 50. fail() try { // do stuff... fail("Exception not thrown"); } catch(Exception e){ assertTrue(e.hasSomeFlag()); }
  • 51. fail() ● Fundamentally not bad, but better use matchers for expected failure ● Matchers help to clarify test intention ● Don’t forget - expected behaviour is an opposite of a failing test
  • 52. Anti-pattern: The Ugly Mirror http://www.iwillnotdiet.com/?attachment_id=2605
  • 53. Anti-pattern: The Ugly Mirror @Test public void personToStringShouldIncludeNameAndSurname() { Person person = new Person("Волк", "Серый"); String expected = "Person[" + person.getName() + " " + person.getSurname() + "]" assertEquals(expected, person.toString()); }
  • 54. Anti-pattern: The Ugly Mirror @Test public void personToStringShouldIncludeNameAndSurname() { Person person = new Person("Волк", "Серый"); String expected = "Person[" + person.getName() + " " + person.getSurname() + "]" assertEquals(expected, person.toString()); }
  • 55. Anti-pattern: The Ugly Mirror @Test public void personToStringShouldIncludeNameAndSurname() { Person person = new Person("Волк", "Серый"); assertEquals("Person[Волк Серый]", person.toString()); }
  • 56. How to turn off the test? http://namo-rekonstrukcija.blogspot.com/2013/05/elektra-izeminimas.html
  • 57. Why would you want to turn off the test?
  • 58. Why would you want to turn off the test? Well, because it fails… :)
  • 59. Ignoring tests ● Always use ignore/pending API from your test library (JUnit @Ignore) @Ignore("charge simplicator not ready") @Test public void shouldChargeMonthly() { //implementation which fails }
  • 60. Ignoring tests ● Do not comment out or false assert your test //Will fix it later™ //@Test public void shouldBeZeroInitialy() { // assertEquals(0, account.getBalance()); //} @Test public void shouldBeZeroInitialy() { assertEquals(1, account.getBalance()); }
  • 61. Ignoring tests ● Do not comment out or false assert your test //Will fix it later™ //@Test public void shouldBeZeroInitialy() { // assertEquals(0, account.getBalance()); //} @Test public void shouldBeZeroInitialy() { assertEquals(1, account.getBalance()); } Who is Will?
  • 62. Ignoring tests ● If you do not need a test - delete it
  • 63. What to do with exceptions? http://s273.photobucket.com/user/eliteskater08/media/meateatingrabbit.jpg.html
  • 64. Exceptions ● If you can, use matchers instead of ○ @Test(expected=?) ○ try-catch approach
  • 65. JUnit expected exception @Test(expected=IndexOutOfBoundsException.class) public void shouldThrowIndexOutOfBoundsException() { ArrayList emptyList = new ArrayList(); Object o = emptyList.get(0); } //matcher in Specs2 (Scala) server.process(None) must throwA[NothingToProccess]
  • 66. try and catch public void shouldThrowIndexOutOfBoundsException() { ArrayList emptyList = new ArrayList(); try { Object o = emptyList.get(0); fail("Should throw IndexOutOfBoundsException"); } catch(IndexOutOfBoundsException e)){ //consider asserting message! } }
  • 68. catch-exception lib List myList = new ArrayList(); catchException(myList).get(1); assertThat(caughtException(), allOf( is(IndexOutOfBoundsException.class), hasMessage("Index: 1, Size: 0"), hasNoCause() ) );
  • 69. Exceptions ● What about ExpectedException Rule? ○ My personal opinion - not that intuitive ○ breaks arrange/act/assert flow
  • 70. ExpectedException rule @Rule public ExpectedException exception = ExpectedException.none(); @Test public void testExpectedException() { exception.expect(IllegalArgumentException.class); exception.expectMessage(containsString('Invalid age')); new Person('Vilkas', -1); } //Person constructor public Person(String name, int age) { if (age <= 0) throw new IllegalArgumentException('Invalid age:' + age); // ... }
  • 72. Problem public class MyService { ... public void process(LocalDate date) { if (date.isBefore(LocalDate.now()) { ... } else { ... } } }
  • 73. Testing with Time ● Design your system where time is a collaborator ● Inject test specific time provider in your test ○ constant time ○ slow time ○ boundary cases time
  • 74. Control time with Clock public class MyService { private Clock clock; // dependency inject ... public void process(LocalDate date) { if (date.isBefore(LocalDate.now(clock)) { ... } else { ... } } }
  • 76. Collections - multiple properties to assert ● Is null? ● Size ● Order ● Content
  • 77. Collections ● Most of the time you want to assert on collection content assertThat(users, containsInAnyOrder("andrius", "vaidas"))
  • 78. Collections ● Prefer exact content matching assertThat(users, contains("andrius", "vaidas"))
  • 79. Collections ● Avoid incomplete assertions //users=List.of("andrius", "vaidas", "valdemaras", "jonas") assertThat(users, hasItems("andrius", "vaidas"))
  • 80. Collections ● Do not sort just because it is easier to assert! assertThat(sort(users), contains("andrius", "vaidas"))
  • 81. Collections ● Multiple assertions are worse than single content assertion assertThat(users, hasSize(2)) assertThat(users, hasItems("andrius", "vaidas"))
  • 84. Random values in tests ● Most of the time you do not want it @Test public void shouldStartWithFirst() { String a = randomString(); String b = randomString(); assertThat(a + b, startsWith(a)); }
  • 85. Random values in tests ● Unless you depend on randomness a lot (eg. password generation*) *Thanks to Aleksandar Tomovski for a good example
  • 86. Random values in tests ● Use property based testing (which is also hard) //example from ScalaCheck property("startsWith") = forAll { (a: String, b: String) => (a+b).startsWith(a) }
  • 87. Random values in tests ● Do not make dummy values random cat = new Cat(randomString()); cat = new Cat("dummyName");
  • 88. What if we still need random cases?
  • 89. Generate Multiple Test Cases ● Quality over quantity
  • 90. Generate Multiple Test Cases ● Quality over quantity ● Think of boundary cases, that you may want to detect with random test
  • 91. Generate Multiple Test Cases ● Quality over quantity ● Think of boundary cases, that you may want to detect with random test ● Use parameterized tests
  • 92. Generate Multiple Test Cases ● Quality over quantity ● Think of boundary cases, that you may want to detect with random test ● Use parameterized tests ● Random is hard to repeat
  • 93. Generate Multiple Test Cases ● Quality over quantity ● Think of boundary cases, that you may want to detect with random test ● Use parameterized tests ● Random is hard to repeat ● Flickering tests
  • 94. How many assertions per test? http://dailypicksandflicks.com/2012/05/11/daily-picdump-455/4-beers-at-the-same-time/
  • 95. How many assertions per test? ● Unit test - one assertion per test. Must be clear and readable ● Proper tests should fail for exactly one reason ● End to end - best case one assertion per test, but more are allowed ● Consider custom matchers
  • 96. How many assertions per test? ● Unit test - one assertion per test. Must be clear and readable ● Proper tests should fail for exactly one reason ● End to end - best case one assertion per test, but more are allowed ● Consider custom matchers
  • 97. Thing #13 Decoupling in End-to-end tests
  • 98. What can be better in this test? [pseudocode] @Test shouldRetrieveUserByLogin() { String userJson = "{"username": "vaidas"}"; HttpRequest post = new Post("https://localhost:8080/users", userJson); HttpResponse postResp = HttpClient().execute(post); assertThat(postResp.status, is(200)); HttpRequest get = new Get("https://localhost:8080/users/vaidas"); HttpResponse getResp = HttpClient().execute(get); User user = mapper.readValue(getResp, User.class); assertThat(user.username, is("vaidas")); }
  • 99. What can be better in this test? [pseudocode] @Test shouldRetrieveUserByLogin() { String userJson = "{"username": "vaidas"}"; HttpRequest post = new Post("https://localhost:8080/users", userJson); HttpResponse postResp = HttpClient().execute(post); assertThat(postResp.status, is( 200)); HttpRequest get = new Get("https://localhost:8080/users/vaidas"); HttpResponse getResp = HttpClient().execute(get); User user = mapper.readValue(getResp, User.class); assertThat(user.username, is("vaidas")); }
  • 100. Decoupling from low level details [pseudocode] @Test shouldRetrieveUserByUsername() { CreateUserResponse createResp = aCreateUserRequest().withUsername("vaidas").execute(); assertThat(createResp, isSuccessful()); GetUserResponse getResp = aGetUserRequest().withUsername("vaidas").execute(); assertThat(getResp, allOf(isSuccessful(), hasUsername("vaidas"))); }
  • 101. Summary ● Context matters ● Testings is controversial topic ● And very opinionated