Upload
lukasz-zakrzewski
View
225
Download
0
Embed Size (px)
Citation preview
Testy integracyjne
Kilka słów o sobie
Łukasz Zakrzewski
- http://lzakrzewski.com
- http://github.com/lzakrzewski
- @lzakrzewski_php
- http://clearcode.cc/
CEL PREZENTACJI
Piramida testów
Dlaczego testy integracyjne są istotne?
Manualny test integracyjny - Given
Manualny test integracyjny - When
Manualny test integracyjny - Then
Testy integracyjne - automatyzacja
KORZYŚCI
PRZYKŁADY
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); }}
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); }}
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
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()); }}
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); }}
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()); }}
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); }}
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 ); }}
PRAKTYKA
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); }}
Test driven development - cz. 2
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); }}
Test driven development - cz. 4
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); }}
Feedback
PERFORMANCE
Profilowanie
Edge-cases
Set-up bazy danych
SQLite - konfiguracja
doctrine: dbal: driver: pdo_sqlite path: "%kernel.cache_dir%/test.db"
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(); }}
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); }}
Fake, stub - cz. 2
//...
interface FacebookApi{ /** * Returns a user node as array. * * @param string $accessToken * * @return array */ public function me($accessToken);}
Fake, stub - cz. 3
//...
class FakeFacebookApiAdapter implements FacebookApi{ /** {@inheritdoc} */ public function me($accessToken) { return [ 'id' => '10203138100203984', 'name' => 'DolorAmit LoremIpsum', ]; }}
PODSUMOWANIE
PYTANIA ?
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