Sexy unit testy. czyli o kilku praktykach w testach jednostkowych



Podobne dokumenty
METODY PROGRAMOWANIA

Gdzie jest moja tabela?

WYKORZYSTANIE JĘZYKA GROOVY W TESTACH JEDNOSTKOWYCH, INTEGRACYJNYCH I AUTOMATYCZNYCH. Mirosław Gołda, Programista Java

Tworzenie aplikacji w języku Java

Wykład 2 Wybrane konstrukcje obiektowych języków programowania (1)

Programowanie obiektowe

Programowanie poprzez testy z wykorzystaniem JUnit

Java: interfejsy i klasy wewnętrzne

Kurs programowania. Wykład 13. Wojciech Macyna. 14 czerwiec 2017

Testy jednostkowe - zastosowanie oprogramowania JUNIT 4.0 Zofia Kruczkiewicz

Testowanie II. Celem zajęć jest zapoznanie studentów z oceną jakości testów przy wykorzystaniu metryk pokrycia kodu testami (ang. code coverage).

Programowanie obiektowe

Programowanie kontraktowe w Javie

Całościowe podejście do testowania automatycznego dla programistów. (TDD, BDD, Spec. by Example, wzorce, narzędzia)

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Zwinna współpraca programistów i testerów z wykorzystaniem BDD i. by Example (JBehave/Spock/SpecFlow)

Współbieżność w środowisku Java

Testowanie aplikacji Java Servlets

Java. Programowanie Obiektowe Mateusz Cicheński

Testy automatyczne. Korzystające z junit

Dokumentacja techniczna API systemu SimPay.pl

Instrukcja 10 Laboratorium 13 Testy akceptacyjne z wykorzystaniem narzędzia FitNesse

Podstawy programowania obiektowego

Zaawansowane aplikacje WWW - laboratorium

Badania poziomu bezpieczeństwa portalu dostępowego do infrastruktury projektu PL-Grid

Podejście obiektowe. Tablice obiektów Przykład 1 metody i atrybuty statyczne oraz niestatyczne

Laboratorium 03: Podstawowe konstrukcje w języku Java [2h]

Dzisiejszy wykład. Wzorce projektowe. Visitor Client-Server Factory Singleton

Iteracyjno-rozwojowy cykl oprogramowania cykl 2. Java Zofia Kruczkiewicz 1

METODY PROGRAMOWANIA

Wzorce logiki dziedziny

Singleton. Cel: Przykład: Zastosowanie: Zapewnienie, że klasa ma tylko jedną instancję i dostarczenie globalnego dostępu do niej.

Optimizing Programs with Intended Semantics

Programowanie obiektowe

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

public enum Environment { Development("Deweloperskie"), Test("Testowe"), Production("Produkcyjne"); private String name;

Klasy. dr Anna Łazińska, WMiI UŁ Podstawy języka Java 1 / 13

Java niezbędnik programisty spotkanie nr 9. Java 2 Platform, Standard Edition 5.0

Automaty do zadań specjalnych. Olga Maciaszek-Sharma, Artur Kotow Wersja 1,

Zaawansowane aplikacje internetowe laboratorium REST

Testowanie II. Cel zajęć. Pokrycie kodu

Wstęp do ruby dla programistów javy

BEAN VALIDATION. Waldemar Korłub. Narzędzia i aplikacje Java EE KASK ETI Politechnika Gdańska

Wątki. Definiowanie wątków jako klas potomnych Thread. Nadpisanie metody run().

Wprowadzenie do testów jednostkowych. Marcin Dziedzic, Wiktor Żołnowski

Wstęp. Ale po co? Implementacja

Platformy Technologiczne

Program szkolenia: Receptury testowania automatycznego - problemy, strategie, taktyki, techniki, narzędzia

Wprowadzenie db4o - podstawy db4o - technikalia Przydatne wiadomości. Wprowadzenie. db4o. Norbert Potocki. 1 czerwca Norbert Potocki db4o

Platformy Programistyczne Podstawy języka Java

Zmiany techniczne wprowadzone w wersji Comarch ERP Altum

Automatyczne testowanie aplikacji Android

Aplikacje Internetowe. Najprostsza aplikacja. Komponenty Javy. Podstawy języka Java

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Klasa bazowa i klasy potomne - doskonalenie umiejtnoci projektowania i wykorzystania klas (45 min)

MVC w praktyce tworzymy system artykułów. cz. 1

Laboratorium z przedmiotu: Inżynieria Oprogramowania INP002017_ Laboratorium 11 Testy akceptacyjne z wykorzystaniem narzędzia FitNesse

Programowanie obiektowe

Laboratorium z przedmiotu: Inżynieria Oprogramowania INEK Instrukcja 7

Przykład zastosowania notacji UML dla realizacji zastosowania wzorca Mediator (materiały dla studentów na prawach rękopisu)

Całościowe podejście do testowania automatycznego dla programistów. /C#/PHP (TDD, BDD, Spec. by Example, wzorce, narzędzia)

Zofia Kruczkiewicz, Programowanie obiektowe - java, wykład 2 1

Języki Programowania II Wykład 3. Java podstawy. Przypomnienie

Programowanie obiektowe

Program szkolenia: Test Driven Development (TDD) using Spock or JUnit 5

Programowanie obiektowe

Testowanie jednostkowe. Jacek Starzyński, ZETiIS PW

Diagramy czynności Na podstawie UML 2.0 Tutorial

Programowanie obiektowe w VB cz 2

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Pętle while, for, do while, instrukcje break, continue, switch 1. Pętle

Poznaj ASP.NET MVC. Kamil Cieślak Microsoft Student Partner

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Techniki efektywnego testowania kodu dla programistów Java (Spock

Tworzenie natywnych aplikacji na urządzenia mobilne - PhoneGap Tomasz Margalski

Pierwsza ramka. dr Anna Łazińska, WMiI UŁ Podstawy języka Java 1 / 10

Java Programowanie Obiektowe Ćwiczenie 1- wprowadzenie

Laboratorium Programowania Kart Elektronicznych

JUNIT. Terminologia. Organizacja testów

Klasy i obiekty cz II

Wprowadzenie do technologii JavaServer Faces 2.1 na podstawie

Wieloplatformowe aplikacje sieciowe. dr inż. Juliusz Mikoda mgr inż. Anna Wawszczak

Język JAVA podstawy. Wykład 3, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Wykorzystywanie parsera DOM w programach Java i PL/SQL

[Android] Podstawy programowania

Laboratorium Programowania Kart Elektronicznych

Od wymagań do Javy w mgnieniu oka

Metody dostępu do danych

Metody Metody, parametry, zwracanie wartości

Wprowadzenie do Behaviordriven

Iteracyjno-rozwojowy cykl oprogramowania 4

1. Robert C. Martin: Clean Code: A Handbook of Agile Software Craftsmanship (Czysty Kod: Podręcznik Dobrego Programisty)

Curiously recurring template pattern

Projektowanie obiektowe. dr Jarosław Skaruz

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

JavaScript - korzenie

Podstawy programowania III WYKŁAD 6

Bezstanowe komponenty sesyjne i zdarzenia zwrotne

1. Czynności przygotowujące aplikację działającą na platformie Java SE Biblioteka5 (należy ją pobrać z załącznika z p.1)

Systemy Rozproszone. Spis treści. Temat projektu: Regułowy system analizujacy logi. autorzy: Rafał Sadłowski, Sebastian Falkus, Michał Różycki

Transkrypt:

Sexy unit testy czyli o kilku praktykach w testach jednostkowych

Agenda sekund o samym sobie KILKA zdań o prezentacji kilka przemyśleń pomysłów na ułatwienie sobie życia pytań od publiczności

O mnie Absolwent WMiI UMK Programista Java Wielbiciel Scruma i dobrej roboty W domu gitary, aparaty i kilka piłek

O Prezentacji czyli co będzie, a czego nie usłyszycie Kilka prawdopodobnie przydatnych praktyk Argumentacja za pisaniem testów Recepta na idealne testy Wady podanych praktyk Parametryzacja testów Piosenka na pożegnanie

Hasło Bo jakoś trzeba zacząć... >> Not only working software, but also well-crafted software (http://manifesto.softwarecraftsmanship.org/)

Kilka przemyśleń

#1 Kod testowy jak żona, matka i teś kod produkcyjny zasługuje na dobrą opiekę

#2 Dobre testy są lepszą dokumentacją niż słaby java-doc

#3 Test może być znakomitym wyznacznikiem jakości Twojego kodu

#4 Dobrze napisany test jest odwrotnością dziecka wracającego po miesiącu z wakacji od dziadków (dla bezdzietnych: nie dziwi Cię jego zachowanie)

#5 Sam fakt pokrycia niekoniecznie doprowadza do happy-endu

Przykłady Kilka rzeczy z życia programisty

Brzydki kod produkcyjny testuje się brzydko Item.java public class Item { private Status status; private Item parent; public void mergeitem(item item) { //... if (isclosed(this) && isclosed(item)) { //... //...more if's here private static boolean isclosed(item item) { return item.getstatus() == CLOSED (item.getparent()!= null && item.getparent().getstatus() == CLOSED); //... Może tak? public boolean isclosed() { return status == CLOSED (parent!= null && parent.getstatus() == CLOSED);

testok czytelne nazwy metod testowych PurchaseTest.java public class PurchaseTest { public void testok() { public void testfail() { public void testexception() { Może tak? public void shouldsellitemifexists() { public void shouldnotsellitemifnotavailable() { public void shouldthrowexceptionfornotexistingclient() { public void should_finalize_purchase_if_paid() {

Fluent API & Builders VS litania setterów PurchaseTest.java public void shouldsellitemifavailable() { Item item = createitem(25000l, null, 1, null); //... //... private Item createitem(long price, Long discount, Integer quantity, Integer popularity) { Item item = new Item(); item.setprice(price); item.setdiscount(discount); item.setquantity(quantity); item.setpopularity(popularity); return item; Może tak? public void shouldsellitemifavailable() { Item item = anitem().withprice(25000l).withquantity(1).build(); //...

Given/When/Then CartTest.java public void shouldgettotalprice() { Item bike = anitem().withprice(100000l).withquantity(1).build(); Item ball = anitem().withprice(4000l).withquantity(2).build(); Cart cart = acartbuilder().withitems(bike, ball).build(); Long totalprice = cart.gettotalprice(); assertequals(108000l, totalprice); Może tak? public void shouldgettotalprice() { // given Item bike = anitem().withprice(100000l).withquantity(1).build(); Item ball = anitem().withprice(4000l).withquantity(2).build(); Cart cart = acart().withitems(bike, ball).build(); // when Long totalprice = cart.gettotalprice(); // then assertequals(108000l, totalprice);

Małe podsumowanie początków CartTest.java public void testok() { Item bike = new Item(); bike.setprice(100000l); bike.setquantity(1); Item ball = new Item(); ball.setprice(4000l); ball.setquantity(2); Cart cart = new Cart(); cart.setitems(arrays.aslist(bike, ball)); Long totalprice = cart.gettotalprice(); assertequals(108000l, totalprice); public void shouldgettotalprice() { // given Item bike = anitem().withprice(100000l).withquantity(1).build(); Item ball = anitem().withprice(4000l).withquantity(2).build(); Cart cart = acart().withitems(bike, ball).build(); // when Long totalprice = cart.gettotalprice(); // then assertequals(108000l, totalprice);

Złośliwe buildery (default is evil?) CurrencyServiceTest.java public void shouldreturnnullifnopricedefined() { // given Item item = anitem().build(); // when Long amount = currencyservice.getamountin(item.getprice(), Currency.EUR); // then assertthat(amount).isnull(); Może tak? FAILED (not null) Item item = anitem().build(); + Item item = anitem().withdefaultvalues().build();

Testowanie pojedynczych przypadków CartTest.java public void testtotalprice() { Item ball = anitem().withprice(4000l).withquantity(2).build(); Cart cart = acart().withitems(ball).build(); Long totalprice = cart.gettotalprice(); assertthat(totalprice).isequalto(8000l); ball.setdiscount(1000l); totalprice = cart.gettotalprice(); assertthat(totalprice).isequalto(6000l); Może tak? public void shouldgetwholetotalpriceifnodiscount() { public void shouldgetdecreasedtotalpriceifdiscountexists() {

Bezpośrednie używanie wartości #1 LabelProviderTest.java public void shouldgetitemlabel() { // given Item item = anitem().withname("kosz na śmieci").withquantity(2).build(); // when String label = labelprovider.createlabel(item); // then assertthat(label).isequalto(item.getname().touppercase() + " w ilości " + item.getquantity() + " sztuk"); Może tak? assertthat(label).isequalto("kosz na śmieci w ilości 2 sztuk");

Bezpośrednie używanie wartości #2 OrderServiceTest.java public void shouldextractcustomerfromorderrecord() { // given String record = StringUtils.join( new Object[] {ORDER_ID, CUSTOMER_ID, FIRST_NAME, LAST_NAME, DOB, ADDRESS, ITEM_ID, ITEM_PRICE, ITEM_QUANTITY, DELIMITER); // when Customer customer = orderservice.extractcustomerfromorderrecord(record); // then assertthat(customer.getid()).isequalto(customer_id); assertthat(customer.getfirstname()).isequalto(first_name); assertthat(customer.getlastname()).isequalto(last_name); assertthat(customer.getdob()).isequalto(dob); assertthat(customer.getaddress()).isequalto(address); Może tak? // given String record = "1 233 ZDZISŁAW SAMORÓB 740121 WESOŁA 21,10-111 BĄKOWO 3876 1000L 2"; // when Customer customer = orderservice.extractcustomerfromorderrecord(record); // then assertthat(customer.getid()).isequalto(233); assertthat(customer.getfirstname()).isequalto("zdzisław"); assertthat(customer.getlastname()).isequalto("samorób"); assertthat(customer.getdob()).isequalto(parse("740121", forpattern("yymmdd")).todate()); assertthat(customer.getaddress()).isequalto("wesoła 21, 10-111 BĄKOWO");

Asercje i fluent API CurrencyServiceTest.java // then assertequals(ioexception.class, exception.getclass()); assertequals("cannot read the stream.", exception.getmessage()); Może tak? // then assertthat(exception).isexactlyinstanceof(ioexception.class).hasmessage("cannot read the stream."); AssertJ (fluent assertions for java)

Własne asercje CurrencyServiceTest.java // then assertthat(customer.getid()).isequalto(233l); assertthat(customer.getfirstname()).isequalto("zdzisław"); assertthat(customer.getlastname()).isequalto("samorób"); assertthat(customer.getdob()).isequalto(parse("740121", forpattern("yymmdd")).todate()); assertthat(customer.getaddress()).isequalto("wesoła 21, 10-111 BĄKOWO"); Może tak? CustomerAssertion.assertThat(customer).hasId(233L).hasFirstName("ZDZISŁAW").hasLastName("SAMORÓB").wasBorn(new DateTime().withYear(1974).withMonthOfYear(01).withDayOfMonth(21)).hasAddress("WESOŁA 21, 10-111 BĄKOWO");.wasBorn("1974-01-21")

Różne realne wartości testowe CartTest.java public void shouldextractcustomerfromorderrecord() { // given String record = "1 1 SOME_STRING SOME_STRING 740101 SOME_STRING,SOME_STRING 1 1 1"; // when Customer customer = orderservice.extractcustomerfromorderrecord(record); // then CustomerAssertion.assertThat(customer).hasId(1L).hasFirstName("SOME_STRING").hasLastName("SOME_STRING").wasBorn("19740101").hasAddress("SOME_STRING"); Po porawieniu wartości... CustomerAssertion.assertThat(customer).hasId(233L).hasFirstName("ZDZISŁAW").hasLastName("SAMORÓB").wasBorn("19740101").hasAddress("WESOŁA 21, 10-111 BĄKOWO"); FAILED

Czytelne nazwy zmiennych CartTest.java public void shouldcopyallfromdirectory() { // given Directory directory1 = adirectory().withpath("/home/docs").withfiles("report_1.txt", "report_2.txt").build(); Directory directory2 = adirectory().withpath("/home/download").withfiles("readme.txt").build(); // when directoryservice.copy(directory1, directory2); // then //... A może tak? public void shouldcopyallfromdirectory() { // given Directory source = adirectory().withpath("/home/docs").withfiles("report_1.txt", "report_2.txt").build(); Directory target = adirectory().withpath("/home/download").withfiles("readme.txt").build(); // when directoryservice.copy(source, target); // then //...

Przydatne biblioteki do tworzenia mocków ReportServiceTest.java @Mock private CurrencyService currencyservice; @Mock private OrderService orderservice; @InjectMocks private OrderService orderservice public void shouldgeneratereportineur() { // given given(currencyservice.getrate("eur")).willreturn(415l); given(orderservice.getorders(eq(datetime.parse("2014-05-01")), eq(datetime.parse("2014-05-31")))).willreturn(aslist( anorder().withid(20l).withdate("2014-05-01").withtotalamount(2500l).build(), anorder().withid(30l).withdate("2014-05-31").withtotalamount(3000l).build())); // when String csvreport = reportservice.createmonthlyordersreport(reporttype.csv, new DateTime().withYear(2014).withMonthOfYear(5)); // then //...

Nadmiarowe dane i mockowanie PurchaseServiceTest.java @Mock EmailService emailservice; @Mock GeoService geoservice; @Mock ClientService clientservice; @InjectMocks PurchaseService purchaseservice = new PurchaseService(); @Before public void setup() { when(clientservice.getclientbyhash(anystring())).thenreturn( ClientBuilder.aClient().withId(10L).withName("Jan Kowalski").withSex(Sex.FEMALE).withDOB("1981-04-03").withAddress("Batorego 10 / 3").build()); when(geoservice.getcountry(anystring())).thenreturn(country.pl); //... public void shoulddecreasequantityoncesold() { //... // when boolean confirmed = purchaseservice.confirm("234ij32jf2a83a"); // then assertthat(confirmed).istrue();

Testowanie wyjątków catch-exception* ReportServiceTest.java public void shouldthrowexceptionwhengeneratingreportineurwithratenotfound() { // given given(currencyservice.getrate("eur")).willreturn(null); given(orderservice.getorders(any(datetime.class), any(datetime.class))).willreturn(aslist(anorder().withid(10l).withdate("2014-05-20").withtotalamount(1000l).build())); // when catchexception(reportservice).createmonthlyordersreport(reporttype.csv, new DateTime().withYear(2014).withMonthOfYear(5)); // then assertthat(caughtexception()).isexactlyinstanceof(ioexception.class).hasmessage("cannot find the rate for EUR."); *) Java 8's lambda expressions will make catch-exception redundant. Therefore, this project won't be maintained any longer

Podsumowanie

Pytania i odpowiedzi Kontakt: Łukasz Sawicki sawickil@gmail.com Sexy unit testy czyli o kilku praktykach w testach jednostkowych