38
Testy integracyjne

Testy integracyjne

Embed Size (px)

Citation preview

Page 1: Testy integracyjne

Testy integracyjne

Łukasz Zakrzewski
Automatyzujmy swoją prace,Nie bądzmy programistami F5,Dbajmy o jakość,Testy integracyjne to inwestycja, która się zwraca.
Page 2: Testy integracyjne

Kilka słów o sobie

Łukasz Zakrzewski

- http://lzakrzewski.com

- http://github.com/lzakrzewski

- @lzakrzewski_php

- http://clearcode.cc/

Page 3: Testy integracyjne

CEL PREZENTACJI

Łukasz Zakrzewski
Co mnie zmotywowało
Page 4: Testy integracyjne

Piramida testów

Page 5: Testy integracyjne

Dlaczego testy integracyjne są istotne?

Page 6: Testy integracyjne

Manualny test integracyjny - Given

Łukasz Zakrzewski
Byłem nieświadomy tego że stosuję testy integracyjne
Page 7: Testy integracyjne

Manualny test integracyjny - When

Page 8: Testy integracyjne

Manualny test integracyjny - Then

Page 9: Testy integracyjne

Testy integracyjne - automatyzacja

Page 10: Testy integracyjne

KORZYŚCI

Łukasz Zakrzewski
Oszczędność czasu,Poprawa jakości,Dokumentacja kodu,Obniżenie prawdopodobieństwa regresji.
Łukasz Zakrzewski
Czyli to co nam daje automatyzacja testów integracyjnych
Page 11: Testy integracyjne

PRZYKŁADY

Page 12: Testy integracyjne

Integracja z frameworkiem - kontroler

//...

class UserController extends Controller{ /** * @Rest\Post("/users", name="register_user", defaults={"_format" : "json"}) */ public function registerUserAction(Request $request) { $this->get('examples.use_case.register_user') ->register( $request->get('email'), $request->get('password') );

return new JsonResponse('', 201); }}

Łukasz Zakrzewski
Integracja z kodem ktory nie jest nasz
Łukasz Zakrzewski
Pierwszym przypadkiem
Page 13: Testy integracyjne

Integracja z frameworkiem - test kontrolera

//...

class UserControllerTest extends TestCase{ /** @test */ public function user_can_be_registered() { $userData = ['email' => '[email protected]', 'password' => 'testing1'];

$this->sendJsonRequest('POST', '/users', $userData);

$this->assertResponseStatus(201); }}

Page 14: Testy integracyjne

Integracja z frameworkiem - konfiguracja

services: examples.subscriber.admin_notifier: class: Examples\Subscriber\AdminNotifier arguments: - "@examples.mailer" tags: 0: name: event_subscriber subscribes_to: Examples\Model\UserWasRegistered method: notify

Page 15: Testy integracyjne

Integracja z frameworkiem - test konfiguracji

//...

class AdminNotifierTest extends TestCase{ /** @test */ public function it_notifies_admin_when_user_was_registered() { $this->handle( new UserWasRegistered(1, '[email protected]', new \DateTime('2017-01-01')) );

$this->assertEquals(1, $this->getSentNotificationsCount()); }}

Page 16: Testy integracyjne

Integracja z bazą danych - repozytorium

//...

class ORMUserRepository implements UserRepository{ private $entityManager;

public function __construct(EntityManager $entityManager) { $this->entityManager = $entityManager; }

public function add(User $user) { $this->entityManager->persist($user); $this->entityManager->flush(); }

public function get($id) { return $this ->entityManager ->find(User::class, $id); }}

Page 17: Testy integracyjne

Integracja z bazą danych - test repozytorium

//...

class ORMUserRepositoryTest extends TestCase{ /** @test */ public function it_adds_user() { $this->givenDatabaseIsClear(); $user = new User(1, '[email protected]', 'testing1');

$this->repository->add($user);

$this->assertThatUserWithIdWasCreated(1); }

/** @test */ public function it_gets_user_by_id() { $this->givenDatabaseIsClear(); $this->repository->add( new User(1, '[email protected]', 'testing1') );

$user = $this->repository->get(1);

$this->assertInstanceOf(User::class, $user); $this->assertEquals(1, $user->getId()); $this->assertEquals('[email protected]', $user->getEmail()); }}

Page 18: Testy integracyjne

Integracja z zewnętrznym API - FacebookAPI

//...

class FacebookApiAdapter implements FacebookApi{ const GRAPH_API_ME_URL = 'https://graph.facebook.com/v2.5/me';

private $client;

public function __construct(ClientInterface $client) { $this->client = $client; }

public function me($accessToken) { $request = $this ->client ->createRequest('GET', self::GRAPH_API_ME_URL.'?access_token='.$accessToken);

$response = $this ->client ->send($request);

return json_decode($response->getBody()->getContents(), true); }}

Page 19: Testy integracyjne

Integracja z zewnętrznym API - test

//...

class FacebookApiAdapterTest extends TestCase{ /** @test */ public function it_can_retrieve_user_node_successfully() { $userNode = $this->adapter->me($this->accessToken());

$this->assertEquals( [ 'id' => '10203138100203984', 'name' => 'DolorAmit LoremIpsum', ], $userNode ); }}

Page 20: Testy integracyjne

PRAKTYKA

Page 21: Testy integracyjne

Test driven development - cz. 1

//...

class UserControllerTest extends TestCase{ /** @test */ public function user_can_be_registered() { $userData = ['email' => '[email protected]', 'password' => 'testing1'];

$this->sendJsonRequest('POST', '/users', $userData);

$this->assertResponseStatus(201); }}

Łukasz Zakrzewski
artykuly mowia o tym ze testy wydluzaja czas developmentu ja sie z tym nie zgadzam, bo
Łukasz Zakrzewski
po tescie kontrolera moge przejsc do implementacji usecasu w ktorym rejestrowany jest user a potem implementacji repozytorium w ktorym user jest dodawany
Łukasz Zakrzewski
nawiązanie do tego co wspomnialem o przyspieszeniu developmentu
Łukasz Zakrzewski
Przyspieszenie developmentu
Page 22: Testy integracyjne

Test driven development - cz. 2

Page 23: Testy integracyjne

Test driven development - cz. 3

//...

class UserController extends Controller{ /** * @Rest\Post("/users", name="register_user", defaults={"_format" : "json"}) */ public function registerUserAction(Request $request) { return new JsonResponse('', 201); }}

Page 24: Testy integracyjne

Test driven development - cz. 4

Page 25: Testy integracyjne

Test driven development - cz. 5

//...

class UserController extends Controller{ /** * @Rest\Post("/users", name="register_user", defaults={"_format" : "json"}) */ public function registerUserAction(Request $request) { // Your stuff there ...

return new JsonResponse('', 201); }}

Page 26: Testy integracyjne

Feedback

Łukasz Zakrzewski
refactoring
Łukasz Zakrzewski
upgrejd
Page 27: Testy integracyjne

PERFORMANCE

Page 28: Testy integracyjne

Profilowanie

Page 29: Testy integracyjne

Edge-cases

Łukasz Zakrzewski
validacja email
Page 30: Testy integracyjne

Set-up bazy danych

Page 31: Testy integracyjne

SQLite - konfiguracja

doctrine: dbal: driver: pdo_sqlite path: "%kernel.cache_dir%/test.db"

Page 32: Testy integracyjne

Transakcje

//...

class RepositoryTest extends TestCase{ /** @test */ public function reverting_transaction() { $this->givenDatabaseIsClear(); $this->getEntityManager()->beginTransaction();

$this->add(new Teapot('brand-new-teapot', 10.0)); $this->add(new Phone('amazing-phone', 400.0));

$items = ItemRepository::create($this->getEntityManager()) ->paginate(1, 2);

$this->assertCount(2, $items);

$this->getEntityManager()->rollback(); }}

Page 33: Testy integracyjne

Fake, stub - cz. 1

//...

class FacebookApiAdapter implements FacebookApi{ const GRAPH_API_ME_URL = 'https://graph.facebook.com/v2.5/me';

/** @var ClientInterface */ private $client;

public function __construct(ClientInterface $client) { $this->client = $client; }

/** {@inheritdoc} */ public function me($accessToken) { $request = $this ->client ->createRequest('GET', self::GRAPH_API_ME_URL.'?access_token='.$accessToken);

$response = $this ->client ->send($request);

return json_decode($response->getBody()->getContents(), true); }}

Page 34: Testy integracyjne

Fake, stub - cz. 2

//...

interface FacebookApi{ /** * Returns a user node as array. * * @param string $accessToken * * @return array */ public function me($accessToken);}

Page 35: Testy integracyjne

Fake, stub - cz. 3

//...

class FakeFacebookApiAdapter implements FacebookApi{ /** {@inheritdoc} */ public function me($accessToken) { return [ 'id' => '10203138100203984', 'name' => 'DolorAmit LoremIpsum', ]; }}

Page 36: Testy integracyjne

PODSUMOWANIE

Łukasz Zakrzewski
2 główne zalety
Łukasz Zakrzewski
przyklady byly dosc podstawowe, mialo to na celu przedstawienie idei
Łukasz Zakrzewski
szybkoscjakosczachecenieniewychodzenie z przegladarki
Page 37: Testy integracyjne

PYTANIA ?

Page 38: Testy integracyjne

Linki:

https://github.com/lzakrzewski/DoctrineDatabaseBackup

http://lzakrzewski.com/2016/02/tricks-to-speed-up-database-tests/

https://github.com/lzakrzewski/tests-with-database-examples

https://blackfire.io

http://symfony.com/doc/current/book/testing.html#functional-tests