object-oriented junit tests

38
/38 @yegor256 1 Yegor Bugayenko Object-Oriented JUnit Tests

Upload: yegor-bugayenko

Post on 22-Jan-2018

259 views

Category:

Technology


2 download

TRANSCRIPT

/38@yegor256 1

Yegor Bugayenko

Object-Oriented JUnit Tests

/38@yegor256 2

Why OOP?

/38@yegor256 3

yegor256/hangman11

@funivan

/38@yegor256 4

Volume 2

$20Free shipment

/38@yegor256 5Unit testing anti-patterns:Happy Path Tests Validation and Boundary Easy Tests The Giant The Cuckoo The Conjoined Twins The Slow Poke Anal Probe Test It All Line Hitter Wait and See The Silent Catcher Chain Gang

The Mockery The Free Ride The Local Hero Wet Floor The Flickering Test The Environmental Vandal Second Class Citizens The Secret Catcher Logic in Tests Code Matching Misleading Tests Not Asserting Asserting on Not-Null

Forty Foot Pole Test With No Name Excessive Setup The Dead Tree The Turing Test The Mother Hen The Sleeper The Butterfly Doppelgänger The Inspector Structured Inspection The Cupcake

/38@yegor256

Dependencies

6

are evil

Unbreakable

/38@yegor256 7

class Book { private int id; String title() { return Database.getInstance().fetch( “SELECT title FROM book WHERE id=?”, this.id ); } } String title = new Book().title();

/38@yegor256 8

Book

BookTest

DatabaseSomething

/38@yegor256 9

class Book { private int id; String title() { return DbUtils.fetch( “SELECT title FROM book WHERE id=?”, this.id ); } }

static

Johan Haleby

/38@yegor256 10

class Book { private int id; String title() { return Database.getInstance().fetch( “SELECT title FROM book WHERE id=?”, this.id ); } }

global

/38@yegor256 11

class DbUtils { private static int port; static String fetch(String sql) { // .. } }

class Database { private static Database INSTANCE; private int port; private Database() {} static Database getInstance() { if (Database.INSTANCE == null) { Database.INSTANCE = new Database(); } return Database.INSTANCE; } String fetch(String sql) { // .. } }

/38@yegor256 12

class DbUtils { private static int port; static String fetch(String sql) { // .. } }

class Database { private static Database INSTANCE; private int port; private Database() {} static Database getInstance() { if (Database.INSTANCE == null) { Database.INSTANCE = new Database(); } return Database.INSTANCE; } static void setInstance(Database db) { Database.INSTANCE = db; } String fetch(String sql) { // .. } }

/38@yegor256 13

class Book { private int id; String title() { return new Database().fetch( “SELECT title FROM book WHERE id=?”, this.id ); } }

new

/38@yegor256 14

class Book { private int id; private Database database; Book() { this(new Database()); } Book(Database db) { this.database = db; } String title() { return this.database.fetch( “SELECT title FROM book WHERE id=?”, this.id ); } }

Dependency Injection

/38@yegor256 15

new Book(new NotRealDatabase());

class NotRealDatabase implements Database { // ... }

interfaces

@Override

/38@yegor256 16

static evil!

singletonsnewinterface-less

/38@yegor256

Mocking

17

is evil

Ad hoc

/38@yegor256 18

static import org.mockito.Mockito.*; class BookTest { @Test public canFetchTitleFromDatabase() { Database db = mock(Database.class); doReturn(“UML Distilled”).when(db).fetch( “SELECT title FROM book WHERE id=?”, 123 ); Book book = new Book(db, 123); assert book.title().equals(“UML Distilled”); } }

/38@yegor256 19

mocking

algorithm

/38@yegor256 20

Book

BookTest

db

assumptions

/38@yegor256 21

Safety net.(c) By John M, CC BY-SA 2.0

/38@yegor256 22

static import org.mockito.Mockito.*; class BookTest { @Test public canFetchTitleFromDatabase() { Database db = mock(Database.class); doReturn(“UML Distilled”).when(db).fetch( “SELECT title FROM book WHERE id=?”, 123 ); Book book = new Book(db, 123); assert book.title().equals(“UML Distilled”); } }

class Book { private int id; private Database database; Book(Database db, int i) { this.database = db; this.id = i; } String title() { return this.database.fetch( “SELECT title FROM book WHERE id=?”, this.id ); } }

/38@yegor256 23

False positives.

/38@yegor256 24

Fakes or doubles.

/38@yegor256 25

class BookTest { @Test public canFetchTitleFromDatabase() { Book book = new Book( new FakeDatabase(), 123 ); assert book.title().equals(“UML Distilled”); } }

class Book { private int id; private Database database; Book(Database db, int i) { this.database = db; this.id = i; } String title() { return this.database.fetch( “SELECT title FROM book WHERE id=?”, this.id ); } }

/38@yegor256 26

class BookTest { @Test public canFetchTitleFromDatabase() { Book book = new Book( new FakeDatabase() .withTitle(123, “UML Distilled”) .withTitle(1, “Elegant Objects”) .withUser(“Peter Pan”), 123 ); assert book.title().equals(“UML Distilled”); } }

/38@yegor256 27

Ad hoc mocking.

Fakes.

/38@yegor256

Algorithms

28

are evil

In-method

Maybe!

/38@yegor256 29

cactoos

www.cactoos.org

/38@yegor256 30

class BookTest { @Test public canBuildURL() { Book book = new Book(); book.setLanguage(Locale.RUSSIAN); book.setEncoding(“UTF-8”); book.setTitle(“Дон Кихот”); assert book.getURL().contains(“%D0%94%”); } }

procedural!

/38@yegor256 31

HamcrestAn anagram for “matchers”.

/38@yegor256 32

A test method must have nothing but a single statement:

assertThat()

/38@yegor256 33

assertThat(book, hasTitle(“UML Distilled”));

“We assert that the book behaves as if it has a title.”

/38@yegor256 34

assertThat( book, hasURL( hasPath( containsString( equalTo(“%D0%94%”) ) ) ) );

We assert thatthe book behaves as if it has a URL that behaves as if it has a path that behaves as if it contains a string that behaves as if it is equal to “%D0%94%”.

/38@yegor256 35

/38@yegor256 36

/38@yegor256 37

shorter test methods

why?!

immutable objectsshare matchers

/38@yegor256 38

Quality Award.

$4096