nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

85
QUALITY EXCITES 2014 31 MAJA 2014 GRZEGORZ GAŁĘZOWSKI MOTOROLA SOLUTIONS

Upload: future-processing

Post on 25-May-2015

686 views

Category:

Technology


1 download

DESCRIPTION

Grzegorz Gałęzowski - prezentacja z III edycji konferencji Quality Excites.

TRANSCRIPT

Page 1: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

QUALITY EXCITES 201431 MAJA 2014

GRZEGORZ GAŁĘZOWSKIMOTOROLA SOLUTIONS

Page 2: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

GRZEGORZ GAŁĘZOWSKIMOTOROLA SOLUTIONS

NIE ROZWIĄZUJ W TESTACHJEDNOSTKOWYCH PROBLEMÓW Z TESTOWANYM KODEM

Page 3: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

BĘDZIE O...

TESTACH JEDNOSTKOWYCH

I PROJEKTOWANIU

ORAZ ICH ZWIĄZKU

NA 5 PRZYKŁADACH

Page 4: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem
Page 5: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

TESTY W MOIM ŚWIECIE...

Page 6: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

Lista TODOCzy zaimplementowałem wszystko?

Page 7: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

AnalizaCzy wiem, co buduję?

Page 8: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

Wykonywalna dokumentacjaCzego "klient" może od kodu oczekiwać?

Page 9: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

ProjektowanieJak rozbić problem?

Page 10: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

TESTY JEDNOSTKOWEDAWNIEJ I DZIŚ

Page 11: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

"the tests must be kept to the same level of high quality as the production code. (...) Duplication must be eliminated from them."

Robert C. Martin

Page 12: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

ROZWIĄZANIANA POZIOMIEAUTOMATYZACJI

Page 13: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

METODY SETUP

[SetUp] public void SetTheStage(){ this.valueUsedEverywhere = 12;

}

Page 14: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

DZIEDZICZENIE KLAS

[TestFixture] public class AuthorizationBehaviors : TestBase

Page 15: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

METODY POMOCNICZE

message = createMessageFor("Ala");

Page 16: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem
Page 17: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

JAKOŚĆ JEDNOSTKI:SPÓJNOŚĆ I POWIĄZANIA

Page 18: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

SPÓJNOŚĆ ~ JEDNA RZECZ

A B

C D

Page 19: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

AB

C D

SPÓJNOŚĆ ~ JEDNA RZECZ

Page 20: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

AB

CD

SPÓJNOŚĆ ~ JEDNA RZECZ

Page 21: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

POWIĄZANIA – KOGO KLASA ZNA?

A

B

C

D

Page 22: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

MOCKI – "SYMULATORY" OBIEKTÓW

ATEST

Page 23: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

SPÓJNOŚĆ I POWIĄZANIAA TESTY

Page 24: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

TEST JEDNOSTKOWY TO KLIENT KODU

Jednostka

KlientTest

Test

TestTest

Test

Test

Test

Page 25: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

ŹLE ZAPROJEKTOWANA JEDNOSTKA...

Jednostka

KlientTest

Test

TestTest

Test

Test

Test

Page 26: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

...JEST TRUDNO TESTOWALNA

Jednostka

KlientTest

Test

TestTest

Test

Test

Test

Page 27: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

SŁUCHAJ ŚLEPOSWOICH TESTÓW

Page 28: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

KORZYŚCI Z ˶SŁUCHANIA TESTÓW˝

Lepszy design produktu• większa spójność• mniej powiązań

Lepsza utrzymywalność testów

Page 29: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PIĘĆ PRZYKŁADÓW

Page 30: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

UWAGA! ZŁY KOD!

Page 31: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PRZYKŁAD 1:

NACHODZENIEZAKRESUTESTÓW

Page 32: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

validation = new SanityValidation();

info = new PersonInfo(); info.Name = "Zenek"; info.Surname = "Kowalski"; info.Age = VALID_AGE;

Assert.DoesNotThrow( () => validation.Of(info));

Page 33: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

validation = new SanityValidation();

info = new PersonInfo(); info.Name = "$"; info.Surname = "Kowalski"; info.Age = VALID_AGE;

Assert.Throws<InvalidValueException>(

() => validation.Of(info));

Page 34: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

validation = new SanityValidation();

info = new PersonInfo(); info.Name = "Zenek"; info.Surname = "$"; info.Age = VALID_AGE;

Assert.Throws<InvalidValueException>(

() => validation.Of(info));

Page 35: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

validation = new SanityValidation();

info = new PersonInfo(); info.Name = "Zenek"; info.Surname = "Kowalski"; info.Age = VALID_AGE – 1;

Assert.Throws<InvalidValueException>(

() => validation.Of(info));

Page 36: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PÓKI CO...

Name Surname Age

Page 37: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

UTRZYMYWALNOŚĆ

Name Surname Age Country

Page 38: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

Name Surname Age Country

UTRZYMYWALNOŚĆ

Wskazówka: Nachodzenie na siebie zakresów testów.

Page 39: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

˶NADPISZ JEDNO POLE˝ - OK, ALE...

validation = new SanityValidation();

info = CreateValidPersonInfo();info.Name = CreateInvalidName();

Assert.Throws<InvalidValueException>(

() => validation.Of(info));

Page 40: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

˶NADPISZ JEDNO POLE˝ - OK, ALE...

validation = new SanityValidation();

info = CreateValidPersonInfo();info.Name = CreateInvalidName();

Assert.Throws<InvalidValueException>(

() => validation.Of(info));

Wskazówka: Testy różnych zachowań

padają z tego samego powodu

Page 41: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

MAŁA SPÓJNOŚĆ

SanityValidation

Walidacja Surname

Walidacja Age

Testy Surname

Testy Age

Of(x)

Testy Name Walidacja Name

Walidacja Surname

Walidacja Age

Page 42: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

ZACHOWANIA SOBIE PRZESZKADZAJĄ

SanityValidationWalidacja Name

Walidacja Surname

Walidacja Age

Testy Surname

Testy Age

Of(x)

Testy Name

Page 43: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

ZACHOWANIA SOBIE PRZESZKADZAJĄ

SanityValidation

Walidacja Surname

Walidacja AgeTesty Age

Of()

Testy Name Walidacja Name

Walidacja Surname

Walidacja Age

Testy Surname

Page 44: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

ZACHOWANIA SOBIE PRZESZKADZAJĄ

SanityValidation

Walidacja Surname

Walidacja Age

Testy Surname Of(x)

Testy Name Walidacja Name

Walidacja Surname

Walidacja AgeTesty Age

Page 45: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PODZIAŁ LEPSZA SPOJNOSĆ

PartialValidations

Walidacja Name

Walidacja Surname

Walidacja Age

SanityValidation

Of(x)

PersonInfo

Page 46: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

UWSPÓLNIENIE

SanityValidation PartialValidations

Walidacja Napisu

Walidacja Minimum

Of(x)

PersonInfo

Page 47: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

MAMY DANE I FUNKCJĘ

SanityValidation PartialValidations

Walidacja Napisu

Walidacja Minimum

Of(x)

PersonInfo

Page 48: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

LEPSZA ABSTRAKCJA

Person

Validate()

PartialValidations

Walidacja Napisu

Walidacja MinimumPersonInfo

Page 49: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

TEST PERSON: UŻYWA WALIDACJI?

Person

Validate()

PersonInfo

Test Validate()

PartialValidations

Mock

Page 50: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

TESTY WALIDACJI NAPISU

PartialValidations

Walidacja Napisu

Walidacja Minimum

Testy Napisu

Testy Minimum

Page 51: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

TEST WALIDACJI MINIMUM

Validations

Walidacja MinimumTesty Minimum

Walidacja NapisuTesty Napisu

Page 52: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PRZYKŁAD 2:

KOMBINACJEFUNKCJONALNOŚCI

Page 53: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

var processing = new MessageProcessing();

messageProcessing.Encryption = true;messageProcessing.Translation = true;messageProcessing.Compression = true;

processing.For(message);

...

...

Page 54: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

var processing = new MessageProcessing();

messageProcessing.Encryption = true;messageProcessing.Translation = true;messageProcessing.Compression = true;

processing.For(message);

...

...

Wskazówka: Eksplozja Kombinacji

Page 55: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

[TestCase(true, true, true)]public void ShouldProcessMessage( bool encrypt, bool translate, bool compress){processing = new MessageProcessing();processing.Encryption = encrypt;processing.Translation = translate;processing.Compression = compress;//...

Page 56: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

[TestCase(true , true , true )][TestCase(false, true , true )][TestCase(true , false, true )][TestCase(true , true , false)][TestCase(false, false, true )][TestCase(true , false, false)][TestCase(false, true , false)][TestCase(false, false, false)]public void ShouldProcessMessage( bool encrypt, bool translate, bool compress)

Page 57: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

ZBYT WIELE ODPOWIEDZIALNOŚCI

MessageProcessing

Walidacja Surname

Walidacja Age

For(msg)

Encryption

Translation

Compression

Page 58: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PODZIAŁ NA MNIEJSZE OBIEKTY

MessageProcessing

For(msg)

Encryption

Translation

Compression

Page 59: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

WYŁĄCZANIE TRANSFORMACJI

MessageProcessing

For(msg)

NullEncryption

Translation

Compression

Page 60: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

TEST PRZETWARZANIA - LEPIEJ, ALE...

MessageProcessing

For(msg)

(1)

(2)

(3)

Page 61: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

TEST PRZETWARZANIA - LEPIEJ, ALE...

MessageProcessing

For(msg)Wskazówka:

Dużo różnych mocków na test

Page 62: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

WSPÓLNY MIANOWNIK...

MessageProcessing

Encryption

Translation

Compression

For(msg)

Page 63: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PODZIAŁ OBIEKTÓW

MessageProcessing

For(m)

EncryptionTranslation Compression

TransformationTransformationTransformation

Page 64: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

TEST PRZETWARZANIA – JESZCZE RAZ

MessageProcessing

For(m)

Page 65: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PRZYKŁAD 3:

ŁAŃCUCHY ZALEŻNOŚCI

Page 66: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

MOCKI - LEGENDA

Utworzenie:mock = Substitute.For<Interface>()

Zaprogramowanie rezultatu wywołanie metody:mock.GetSomething().Returns(something);

Page 67: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

system = Substitute.For<System>();radio = Substitute.For<Radio>();owner = Substitute.For<User>();

system.GetRadio(1).Returns(radio);radio.GetOwner().Returns(owner);owner.GetName().Returns(name);

Page 68: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

ZESTAWIANIE ŁAŃCUCHA MOCKÓW

Test

Name

Page 69: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

WSZYSTKO WIDOCZNE PUBLICZNIE

System

Radio

OwnerName

Klient

Page 70: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PROBLEM Z ZALEŻNOŚCIAMI

System

Radio

OwnerName

Klient

Page 71: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PROBLEM Z ZALEŻNOŚCIAMI

System

Radio

OwnerName

Klient

Wskazówka: mocki zwracające mocki

Page 72: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

NAJPROSTSZE ROZWIĄZANIE

System

Radio

OwnerRadioOwnerName

Klient

Page 73: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

ŁATWIEJSZE TESTY

RadioOwnerName

Klient

Page 74: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PRZYKŁAD 4:

MUSZĘ TESTOWAĆ PRYWATNE METODY

Page 75: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

Obiekt

D()B()

C()

A()

- CHCĘ TESTOWAĆ PRYWATNĄ METODĘ

Page 76: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

- ZRÓB TO PRZEZ PUBLICZNE API

Test Obiekt

B()

C()

A()

D()

Page 77: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

- ALE ONA JEST NA TYLE ODRĘBNA...

Test 2 Obiekt

B()

C()

A()

D()

Page 78: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

... ŻE CHCĘ JĄ TESTOWAĆ OSOBNO.

Test 2 Obiekt

B()

C()

A()

D()Wskazówka:

Chęć testowania prywatnych metod

Page 79: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

- TO JĄ WYDZIEL!

Test 2 Obiekt

B()

C()

A()

InnyObiekt

D()

Page 80: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PRZYKŁAD 5:

CIĘŻKI KONTEKST

Page 81: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

configData = new ConfigData();configData.GetHeader().SetStdState(StdState.SUBMITTED);configData.GetHeader().SetType(FileType.NECB);

ge1 = CreateGroupEntry(1, TALKGROUP, null, configData.Id);ge2 = CreateGroupEntry(2, TALKGROUP, null, configData.Id);ge3 = CreateGroupEntry(3, MULTIGROUP, null,

configData.Id);ge4 = CreateGroupEntry(4, MULTIGROUP, null,

configData.Id);ge5 = CreateGroupEntry(5, MULTIGROUP, null,

configData.Id);

talkgroup1 = CreateTalkgroup(1, 1, null, configData.Id);talkgroup2 = CreateTalkgroup(1, 3, null, configData.Id);talkgroup3 = CreateTalkgroup(2, 0, null, configData.Id);talkgroup4 = CreateTalkgroup(3, 5, null, configData.Id);

context = new ValidationObjectContext(configData);

Page 82: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

configData = new ConfigData();configData.GetHeader().SetStdState(StdState.SUBMITTED);configData.GetHeader().SetType(FileType.NECB);

ge1 = CreateGroupEntry(1, TALKGROUP, null, configData.Id);ge2 = CreateGroupEntry(2, TALKGROUP, null, configData.Id);ge3 = CreateGroupEntry(3, MULTIGROUP, null,

configData.Id);ge4 = CreateGroupEntry(4, MULTIGROUP, null,

configData.Id);ge5 = CreateGroupEntry(5, MULTIGROUP, null,

configData.Id);

talkgroup1 = CreateTalkgroup(1, 1, null, configData.Id);talkgroup2 = CreateTalkgroup(1, 3, null, configData.Id);talkgroup3 = CreateTalkgroup(2, 0, null, configData.Id);talkgroup4 = CreateTalkgroup(3, 5, null, configData.Id);

context = new ValidationObjectContext(configData);

Wskazówka: pracochłonne ustawianie kontekstu

Page 83: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

WNIOSKI

Słuchaj ślepo swoich testówUważaj na:

• eksplozje kombinacji• długie testy• testowanie prywatnych metod• mocki zwracające mocki• ciężki kontekst

Szukaj najpierw źródła problemu w designie

Page 84: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

PYTANIA?

Słuchaj ślepo swoich testówUważaj na:

• eksplozje kombinacji• długie testy• testowanie prywatnych metod• mocki zwracające mocki• ciężki kontekst

Szukaj najpierw źródła problemu w designie

Page 85: Nie rozwiązuj w testach jednostkowych problemów z testowanym kodem

MOTOROLA, MOTO, MOTOROLA SOLUTIONS and the Stylized M Logo are trademarks or registered trademarks of Motorola Trademark Holdings, LLC and are used under license. All other trademarks are the property of their respective owners. © 2010 Motorola, Inc. All rights reserved.

iProtect Classification: Public