Refactoring Unit-Tests

Ähnliche Dokumente
Effektiver Einsatz von Code-Reviews

Unit Testing, SUnit & You

Software - Testung ETIS SS05

Fortgeschrittenes Programmieren mit Java. Test Driven Development

Klassenentwurf. Wie schreiben wir Klassen, die leicht zu verstehen, wartbar und wiederverwendbar sind? Objektorientierte Programmierung mit Java

Testen und Testautomatisierung in agilen Projekten

Mocha. Ein Ruby Mocking und Stubbing Framework. von Thilo Utke. Werd ich drüber reden Erst was zu mit.

Testen im Software- Entwicklungsprozess

Effizientes und effektives Testen von Embedded SW mit Google Test. Michael Bernhard

Das Test-Framework JUnit ETIS SS04

Unit Tests mit Junit 4. Dario Borchers

Test-driven development JUnit-Test. Lars Varain

JUnit - Test Driven Development. Bernhard Frey, Thorsten Stratmann, Jackson Takam, Michel Müller 1

Iterativ. Inkrementell

Test-Driven Design: Ein einfaches Beispiel

JUnit. HierarchicalContextRunner. Mehr Struktur. TDD. Clean Code. Verantwortung. Skills. Namics. Stefan Bechtold. Principal Software Engineer.

SEP 114. Design by Contract

Programmierprojekt. Anne0e Bieniusa Sommersemester 2014

Software-Engineering Software-Management

The Art of Unit Testing

Unit Testing mit JUnit. Dr. Andreas Schroeder

Software Engineering in der Praxis

Einführung in die Informatik

Markus Wichmann. Testen von Java Code mit. JUnit

Agiles Testen. Gedankensammlung. 17. November Patrick Koglin

Operationalisierbare Qualitätskriterien für die Programmierung mit Erfahrungen aus PRÜ1 und PRÜ2

JGiven: Ein entwicklerfreundliches BDD-Framework für Java

Testen mit JUnit. Motivation

TDD. mit JUnit & Mockito. Tobias Trelle, codecentric

Programmieren was ist das genau?

Algorithmen und Programmieren II Einführung in Python

Unit Tests. Programmiermethodik. Eva Zangerle Universität Innsbruck

Client-Server-Beziehungen

SEMINAR Modifikation für die Nutzung des Community Builders

Programmieren I. Übersicht. Vorlesung 12. Handout S. 1. Martin Schultheiß. Hochschule Darmstadt Wintersemester 2010/2011

Qualität von Software - Prof. Schlingloff, Lackner - SS2013 DYNAMISCHER TEST. Whitebox Testen mit JUnit

arboro Netto Report für Shopware 4.2.x Version 1.0.1

Einfaches Testen von Webapplikationen mit

Grundzüge der Programmierung. Konzepte der objektorientierten Programmierung (oop) OBJEKTE - KLASSEN

Security Patterns. Benny Clauss. Sicherheit in der Softwareentwicklung WS 07/08

Testen und Debuggen von Webanwendungen

Verzahnung von Detailspezifikationen mit automatisierbaren Testfällen

Programmiertechnik II

Swp08-6 Verantwortliche: Yundensuren, Baigalmaa. Testkonzept

Objektorientierte Programmierung OOP

Testen mit JUnit. Martin Wirsing. Ziele. in Zusammenarbeit mit Michael Barth, Philipp Meier und Gefei Zhang

Babeș-Bolyai Universität Cluj Napoca Fakultät für Mathematik und Informatik Grundlagen der Programmierung MLG5005. Modulare Programmierung

Spock und Geb: Übersichtlich und nachvollziehbar Testen für alle!

Die Invaliden-Versicherung ändert sich

Einführung in die Informatik

Schritt-für-Schritt-Anleitung So verschlüsseln Sie Ihr -Konto in der Software 6.0

U08 Entwurfsmuster (II)

Test Driven Development

Innovation in der Raubtierdressur Neue Wege in der Risikominierung Wolfgang Platz, Founder & CPO

OOSE_02E Testen mit BlueJ/JUnit 4

Prof. Dr. Uwe Schmidt. 21. August Aufgaben zur Klausur Objektorientierte Programmierung im SS 2007 (IA 252)

Einführung in Eclipse und Java

Softwaretests in Visual Studio 2010 Ultimate Vergleich mit Java-Testwerkzeugen. Alexander Schunk Marcel Teuber Henry Trobisch

Testen von graphischen Benutzeroberflächen. 26. Juni 2013

Xcode/Cocoa/Objective-C Crashkurs Programmieren unter Mac OS X

Kurzanleitung JUnit. 1 Grundlagen. 1.1 Begriffsdefinitionen. 1.2 Empfehlungen

07. November, Zürich-Oerlikon

Reinigen der Druckköpfe

Softwareentwicklungsprozess im Praktikum. 23. April 2015

Objektorientierte Programmierung

Java Schulung. Objektorientierte Programmierung in Java Teil IV: Testen mit JUnit. Prof. Dr. Nikolaus Wulff

LIFEWAVE S WAVE-BONUS: ECHTE VERDOPPLUNG. ECHTE ERGEBNISSE.

OOSE4 Testen mit BlueJ/JUnit 4

Hilfe zur ekim. Inhalt:

Kapitel 1: Einführung. Was ist Informatik? Begriff und Grundprobleme der Informatik. Abschnitt 1.1 in Küchlin/Weber: Einführung in die Informatik

Die Welt der SW-Qualität Ein Streifzug in 30 Minuten! Johannes Bergsmann Eigentümer

Algorithmen mit Python

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {...

Probeklausur. Lenz Belzner. January 26, Lenz Belzner Probeklausur January 26, / 16

Kommt Clean Code in Studium und Ausbildung zu kurz?

Unit-Test Theorie und Praxis. Stephan Seefeld, INGTES AG

Grundlagen der Programmierung Prof. H. Mössenböck. 14. Schrittweise Verfeinerung

JUnit. Software-Tests

Komponententest. Testen von Software Systemen. Übung 02 SS 2009 Version:

Lösungen zum Test objektorientierter Software

Whitebox-Tests: Allgemeines

Workshop 6. Einführung in die objektorientierte Programmierung. Teil: Java mit BlueJ

Fachgebiet Informationssysteme Prof. Dr.-Ing. N. Fuhr. Programmierung Prof. Dr.-Ing. Nobert Fuhr. Übungsblatt Nr. 6

Klicken Sie auf Weiter und es erscheint folgender Dialog

Schritt-für-Schritt-Anleitung So verschlüsseln Sie Ihr -Konto in Apple Mail

Free your work. Free your work. Wir wollen Ihnen die Freiheit geben, sich auf Ihr Geschäft zu konzentrieren.

Versionsverwaltung für die KU Betriebssysteme. Eine Einführung

Individuelle Erweiterung des generierten Codes. 16. Januar 2013

Assertions (Zusicherungen)

Entwicklung des Dentalmarktes in 2010 und Papier versus Plastik.

Dokumentation für das Spiel Pong

Transkript:

def test_validate_e_mail @user.e_mail = '' assert!@user.save assert_equal ["is invalid", "can't be blank"], @user.errors.on(:e_mail) @user.e_mail = 'dhjxfgjdxfj' assert!@user.save assert_equal "is invalid", @user.errors.on(:e_mail) @user.e_mail = 'dhjx@fgjdxfj' assert!@user.save assert_equal "is invalid", @user.errors.on(:e_mail) @user.e_mail = 'dhjx@fgjdxf.j' assert!@user.save assert_equal "is invalid", @user.errors.on(:e_mail) @user.e_mail = 'dhjx@fgjd.fj' assert @user.save @user.e_mail = 'dh.jx@fgjdx.fj' assert @user.save Refactoring Unit-Tests Dipl.-Inf. (FH) Marco Emrich Nov 2013 #XDDE13

Realer Code webmasters.de 2005

def test_validate_password @user.password = '' @user.password_confirmation = '' assert!@user.save assert_equal ["is too short (minimum is 5 characters)", "has invalid characters", "can't be blank"], @user.errors.on(:password) @user.password = 'testest' @user.password_confirmation = 'testtest' assert!@user.save assert_equal "doesn't match confirmation", @user.errors.on(:password) @user.password = '' @user.password_confirmation = 'testtest' assert!@user.save assert_equal ["is too short (minimum is 5 characters)", "has invalid characters", "doesn't match confirmation", "can't be blank"], @user.errors.on(:password) @user.password = 'testtest' @user.password_confirmation = '' assert!@user.save assert_equal "doesn't match confirmation", @user.errors.on(:password) @user.password = 'test' @user.password_confirmation = 'test' assert!@user.save assert_equal "is too short (minimum is 5 characters)", @user.errors.on(:password) @user.password = 'testet' @user.password_confirmation = 'testet' assert @user.save

def test_validate_password @user.password = '' @user.password_confirmation = '' assert!@user.save assert_equal ["is too short (minimum is 5 characters)", "has invalid characters", "can't be blank"], @user.errors.on(:password) @user.password = 'testest' @user.password_confirmation = 'testtest' assert!@user.save assert_equal "doesn't match confirmation", @user.errors.on(:password) @user.password = '' @user.password_confirmation = 'testtest' assert!@user.save assert_equal ["is too short (minimum is 5 characters)", "has invalid characters", "doesn't match confirmation", "can't be blank"], @user.errors.on(:password) Peinlich @user.password = 'testtest' @user.password_confirmation = '' assert!@user.save assert_equal "doesn't match confirmation", @user.errors.on(:password) @user.password = 'test' @user.password_confirmation = 'test' assert!@user.save assert_equal "is too short (minimum is 5 characters)", @user.errors.on(:password) @user.password = 'testet' @user.password_confirmation = 'testet' assert @user.save

Es gibt noch Hoffnung

Test Refactoring

Beispiel

Seminar-Shop

Seminar-Shop

Specs Seminare haben Name und Nettopreis Ruby Java

Specs Seminare haben Name und Nettopreis Seminare berechnen Ihren Bruttopreis - außer, sie sind steuerbefreit Ruby Java

Marketing-Abteilung

3-Buchstaben Rabatt

Specs Seminare haben Name und Nettopreis Seminare berechnen Ihren Bruttopreis - außer, sie sind steuerbefreit 3-Buchstaben-Seminare* bekommen 5% Rabatt Ruby Java

class Seminar TAX_RATE = 1.19 THREE_LETTER_DISCOUNT_RATE = 5 attr_writer :net_price, :tax_free, :name def discount_rate discount_granted?? THREE_LETTER_DISCOUNT_RATE : 0 def initialize(name, net_price, tax_free) @name, @net_price, @tax_free = name, net_price, tax_free def gross_price net_price * tax_rate def net_price @net_price - discount def tax_rate @tax_free? 1 : TAX_RATE / 100 def discount @net_price * discount_rate / 100 def discount_granted? @name.size < 3

class Seminar TAX_RATE = 1.19 THREE_LETTER_DISCOUNT_RATE = 5 attr_writer :net_price, :tax_free, :name def discount_rate discount_granted?? THREE_LETTER_DISCOUNT_RATE : 0 def initialize(name, net_price, tax_free) @name, @net_price, @tax_free = name, net_price, tax_free def gross_price net_price * tax_rate def net_price @net_price - discount def tax_rate @tax_free? 1 : TAX_RATE / 100 def discount @net_price * discount_rate / 100 def discount_granted? @name.size < 3

class SeminarTest < Test::Unit::TestCase def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price seminar.net_price = 300 assert_equal 339.15, seminar.gross_price seminar.tax_free = true assert_equal 285, seminar.gross_price seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 300, seminar.gross_price

class SeminarTest < Test::Unit::TestCase def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price seminar.net_price = 300 assert_equal 339.15, seminar.gross_price seminar.tax_free = true assert_equal 285, seminar.gross_price Failure: <565.25> expected but was <5.95>. seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 300, seminar.gross_price

3 Minuten

Fehler gefunden?

2 Fehler gefunden?

3 Fehler gefunden?

Alternative Test-Suite: 9 Testfälle

def test_seminar_should_have_the_german_mwst_tax_rate_if_it_is_not_tax_free seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate Failure: <1.19> expected but was <0.0119>. def test_discount_granted_should_return_true_if_name_consists_of_3_letters seminar = create_seminar(name: 'OOP') # 3 Buchstaben assert seminar.discount_granted? Failure: <false> is not true.

3 Minuten

Fehler gefunden?

2 Fehler gefunden?

3 Fehler gefunden?

class Seminar TAX_RATE = 1.19 THREE_LETTER_DISCOUNT_RATE = 5 attr_writer :net_price, :tax_free, :name def discount_rate discount_granted?? THREE_LETTER_DISCOUNT_RATE : 0 def initialize(name, net_price, tax_free) @name, @net_price, @tax_free = name, net_price, tax_free def gross_price net_price * tax_rate def net_price @net_price - discount def tax_rate @tax_free? 1 : TAX_RATE / 100 def discount @net_price * discount_rate / 100 def discount_granted? @name.size < 3

class Seminar TAX_RATE = 1.19 THREE_LETTER_DISCOUNT_RATE = 5 attr_writer :net_price, :tax_free, :name def discount_rate discount_granted?? THREE_LETTER_DISCOUNT_RATE : 0 def initialize(name, net_price, tax_free) @name, @net_price, @tax_free = name, net_price, tax_free def gross_price net_price * tax_rate def net_price @net_price - discount def tax_rate @tax_free? 1 : TAX_RATE def discount @net_price * discount_rate / 100 def discount_granted? @name.size <= 3

Vergleich der Testsuites

Qualitätskriterien für Testfälle

Qualitätskriterien guter Testfälle hohe Lesbarkeit, leicht zu verstehen Tests sind schwierig zu testen als Dokumentation der Anforderungen verwbar => BDD: Specs

Qualitätskriterien guter Testfälle hohe Lesbarkeit, leicht zu verstehen hohe Ausführungsgeschwindigkeit Häufige Ausführung

Qualitätskriterien guter Testfälle hohe Lesbarkeit, leicht zu verstehen hohe Ausführungsgeschwindigkeit geringer Wartungsaufwand möglichst Redundanzfrei: DRY geringer Test-Overlap geringe Kopplung an den Produktivcode

Qualitätskriterien guter Testfälle hohe Lesbarkeit, leicht zu verstehen hohe Ausführungsgeschwindigkeit geringer Wartungsaufwand gute Defekt-Lokalisierung Rainsberger: Jede Testmethode prüft genau eine interessantes Verhaltensweise

Qualitätskriterien guter Testfälle Lesbar Schnell Wartbar gute Defekt-Lokalisierung

Qualitätskriterien guter Testfälle manchmal Widersprüchliche Anforderungen

Qualitätskriterien guter Testfälle Optimaler Kompromiss?

Kent Beck TDD

http://dannorth.net/bio/ BDD Meet BDD (Dan North oder King Image) Dan North

TDD/BDD führen zu guten Tests!

TDD/BDD führen zu guten Tests! (nicht unbedingt automatisch)

Verbesserungen möglich!

Legacy Test Suites

Testcode muss gewartet werden

Test Refactoring

Beispiel

class SeminarTest < Test::Unit::TestCase def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price seminar.net_price = 300 assert_equal 339.15, seminar.gross_price seminar.tax_free = true assert_equal 285, seminar.gross_price seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 300, seminar.gross_price

class SeminarTest < Test::Unit::TestCase def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price seminar.net_price = 300 assert_equal 339.15, seminar.gross_price seminar.tax_free = true assert_equal 285, seminar.gross_price seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 300, seminar.gross_price Remove Redudant Tests (gleiche Äquivalenzklasse)

class SeminarTest < Test::Unit::TestCase def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price seminar.net_price = 300 assert_equal 339.15, seminar.gross_price seminar.tax_free = true assert_equal 475, seminar.gross_price seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 500, seminar.gross_price Remove Redudant Tests

class SeminarTest < Test::Unit::TestCase def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price seminar.tax_free = true assert_equal 475, seminar.gross_price seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 500, seminar.gross_price

class SeminarTest < Test::Unit::TestCase def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, true) assert_equal 500, seminar.gross_price seminar.name = 'OOP' assert_equal 475, seminar.gross_price seminar.tax_free = false assert_equal 565.25, seminar.gross_price Use neutral fixture (Build up!)

class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, true) assert_equal 500, seminar.gross_price def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, false) assert_equal 595, seminar.gross_price def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = Seminar.new('OOP', 500, true) assert_equal 475, seminar.gross_price Split test methods Fresh fixture Arrange Act Assert: AAA-Pattern

class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, true) assert_equal 500, seminar.gross_price def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, false) assert_equal 595, seminar.gross_price def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = Seminar.new('OOP', 500, true) assert_equal 475, seminar.gross_price Use test data factories

Test data factories Ruby-Frameworks Factory-Girl Machinist Java-Frameworks Patterns Usurper PojoBuilder Object Mothers Test Data Builders Example Factories

class SeminarTest < Test::Unit::TestCase def create_seminar(args = {}) new_args = { :name => 'Object Oriented Programming', :net_price => 500, :tax_free => true }.merge(args) Defaults (neutral Fixture) Seminar.new(new_args[:name], new_args[:net_price], new_args[:tax_free]) Use factories

class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, true) seminar = create_seminar(tax_free: true) assert_equal 500, seminar.gross_price def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, false) seminar = create_seminar(tax_free: false) assert_equal 595, seminar.gross_price def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = Seminar.new('OOP', 500, true) seminar = create_seminar(name: 'OOP') assert_equal 475, seminar.gross_price Use factories

class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = create_seminar(tax_free: true) assert_equal 500, seminar.gross_price def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = create_seminar(tax_free: false) assert_equal 595, seminar.gross_price def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP') assert_equal 475, seminar.gross_price Use factories

class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = create_seminar(tax_free: true) assert_equal seminar.net_price, seminar.gross_price 500 def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = create_seminar(tax_free: false) assert_equal seminar.net_price * Seminar::TAX_RATE, seminar.gross_price 500 def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP', net_price: 500) assert_equal 500 * 0.95, seminar.gross_price Use factories

class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = create_seminar(tax_free: true) assert_equal seminar.net_price, seminar.gross_price def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = create_seminar(tax_free: false) assert_equal seminar.net_price * Seminar::TAX_RATE, seminar.gross_price def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP', net_price: 500) assert_equal 500 * 0.95, seminar.gross_price add missing test

class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = create_seminar(tax_free: true) assert_equal seminar.net_price, seminar.gross_price def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = create_seminar(tax_free: false) assert_equal seminar.net_price * Seminar::TAX_RATE, seminar.gross_price def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP', net_price: 500) assert_equal 500 * 0.95, seminar.gross_price def test_a_more_letters_seminar_should_return_a_net_price_without_discount seminar = create_seminar(name: 'Object O. Programming', net_price: 500) assert_equal 500, seminar.gross_price add missing test

Discount def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP') assert_equal 500 * 0.95, seminar.gross_price def test_a_more_letters_seminar_should_return_a_net_price_without_discount seminar = create_seminar(name: 'Object Oriented Programming') assert_equal 500, seminar.gross_price class Seminar def gross_price net_price * tax_rate def net_price @net_price - discount Isolate def discount @net_price * discount_rate / 100

Discount def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP') assert_equal 500 * 0.95, seminar.net_price.gross_price def test_a_more_letters_seminar_should_return_a_net_price_without_discount seminar = create_seminar(name: 'Object Oriented Programming') assert_equal 500, seminar.net_price.gross_price class Seminar def gross_price net_price * tax_rate def net_price @net_price - discount Isolate def discount @net_price * discount_rate / 100

Tax def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = create_seminar(tax_free: true) assert_equal seminar.net_price, seminar.gross_price def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = create_seminar(tax_free: false) assert_equal seminar.net_price * Seminar::TAX_RATE, seminar.gross_price class Seminar def gross_price net_price * tax_rate Isolate def tax_rate @tax_free? 1 : TAX_RATE / 100

Tax def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal seminar.net_price, seminar.gross_price assert_equal 1, seminar.tax_rate def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal seminar.net_price * Seminar::TAX_RATE, seminar.gross_price assert_equal Seminar::TAX_RATE, seminar.tax_rate class Seminar def gross_price net_price * tax_rate Isolate def tax_rate @tax_free? 1 : TAX_RATE / 100

Tax def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal 1, seminar.tax_rate def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate class Seminar def gross_price net_price * tax_rate Isolate def tax_rate @tax_free? 1 : TAX_RATE / 100

Tax def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal 1, seminar.tax_rate def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate class Seminar def gross_price net_price * tax_rate Lost Coverage def tax_rate @tax_free? 1 : TAX_RATE / 100

Tax def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal 1, seminar.tax_rate def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate def test_seminar_should_use_tax_rate_to_calculate_gross_price class Seminar def gross_price net_price * tax_rate Lost Coverage def tax_rate @tax_free? 1 : TAX_RATE / 100 def net_price @net_price - discount

Tax def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal 1, seminar.tax_rate def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate def test_seminar_should_use_tax_rate_to_calculate_gross_price seminar = create_seminar(tax_free: false) assert_equal?, seminar.gross_price Isolate Use Stubs class Seminar def gross_price net_price * tax_rate def tax_rate @tax_free? 1 : TAX_RATE / 100 def net_price @net_price - discount

Tax def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal 1, seminar.tax_rate def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate def test_seminar_should_use_tax_rate_to_calculate_gross_price seminar = create_seminar(tax_free: false) seminar.stubs(net_price: 100) seminar.stubs(tax_rate: 1.5) assert_equal 150, seminar.gross_price class Seminar def gross_price net_price * tax_rate Isolate Use Stubs def tax_rate @tax_free? 1 : TAX_RATE / 100 def net_price @net_price - discount

Mocks & Stubs Ruby Rspec-Mocks Mocha FlexMock Java EasyMock Mockito Jmockit JavaScript SinonJS Jasmine Spies

BDD-Frameworks Ruby RSpec Shoulda Java JDave Jnario ScalaTest JavaScript Jasmine Mocha more readable!

Github: https://github.com/marcoemrich XING: https://www.xing.com/profile/marco_emrich3 Twitter: @marcoemrich E-Mail: m.emrich@webmasters.de

Hands-On 1)Paare bilden 2)Sprache wählen: Ruby, Java oder JavaScript 3)Code auschecken git clone git@github.com:marcoemrich/testrefactoringkata.git 4)Loslegen :)