Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
MR::Go::Admin::Test
Search
Vadim Pushtaev
January 23, 2017
Programming
0
71
MR::Go::Admin::Test
Vadim Pushtaev
January 23, 2017
Tweet
Share
More Decks by Vadim Pushtaev
See All by Vadim Pushtaev
PyCon Russia 2018 — Unit Testing
vadimpushtaev
0
360
Perl course (5), testing
vadimpushtaev
0
88
Perl course (4), testing
vadimpushtaev
0
90
Perl course (4), db
vadimpushtaev
0
200
Perl course (4), oop
vadimpushtaev
1
170
Perl course (4), mod
vadimpushtaev
0
190
Perl course (3), testing
vadimpushtaev
0
75
Perl course (3), db
vadimpushtaev
0
75
Perl course (3), oop
vadimpushtaev
0
84
Other Decks in Programming
See All in Programming
Fixstars高速化コンテスト2024準優勝解法
eijirou
0
190
PSR-15 はあなたのための ものではない? - phpcon2024
myamagishi
0
400
Асинхронность неизбежна: как мы проектировали сервис уведомлений
lamodatech
0
1.3k
PHPで学ぶプログラミングの教訓 / Lessons in Programming Learned through PHP
nrslib
4
1.1k
サーバーゆる勉強会 DBMS の仕組み編
kj455
1
300
AppRouterを用いた大規模サービス開発におけるディレクトリ構成の変遷と問題点
eiganken
1
440
rails newと同時に型を書く
aki19035vc
5
710
Androidアプリの One Experience リリース
nein37
0
1.1k
Fibonacci Function Gallery - Part 2
philipschwarz
PRO
0
210
毎日13時間もかかるバッチ処理をたった3日で60%短縮するためにやったこと
sho_ssk_
1
540
快速入門可觀測性
blueswen
0
500
テストコードのガイドライン 〜作成から運用まで〜
riku929hr
7
1.4k
Featured
See All Featured
Building Flexible Design Systems
yeseniaperezcruz
328
38k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
25k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
45
2.3k
The Language of Interfaces
destraynor
155
24k
GitHub's CSS Performance
jonrohan
1030
460k
YesSQL, Process and Tooling at Scale
rocio
170
14k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
7k
GraphQLの誤解/rethinking-graphql
sonatard
68
10k
Transcript
MR::Go::Admin::Test
Go::Admin Go
Go::Admin Go Go Go Go Go Go Go Go Go
Go
xUnit
xUnit SUnit
xUnit SUnit JUnit
xUnit SUnit JUnit unittest
xUnit SUnit JUnit unittest runit
xUnit SUnit JUnit unittest runit rspec
xUnit SUnit JUnit unittest runit rspec Test::Class
xUnit Test Patterns Автор: Месарош Джерард
package MR::Go::Admin::User::Test; sub setup : Test(setup) { my ($self) =
@_; $self->{user} = create_user(); } sub test_delete : Test(2) { my ($self) = @_; $self->{user}->delete(); # ... } Test::Class
Именование классов MR::Go::Admin::User → MR::Go::Admin::User::Test
Именование классов MR::Go::Admin::User → MR::Go::Admin::User::Test *::Test запрещены не в тестах
Именование классов MR::Go::Admin::User → MR::Go::Admin::User::Test *::Test запрещены не в тестах
MR::Go::Admin::User::Test::_FakeUser
Именование методов delete → delete delete → delete__already_deleted _delete →
delete delete → test_delete delete → test_delete__already_deleted _delete → test__delete__already_deleted Двойное подчеркивание
https://goo.gl/tBIRwZ sub _set_status { my ($self, $status) = @_; $self->_status($status);
$self->_history->add($status); $self->_log('...'); } sub set_status_processing { return shift->_set_status('processing'); } sub set_status_processed { return shift->_set_status('processing'); } Тестирование приватных методов
Структура теста
Структура теста Arrange Act Assert
Структура теста Arrange Act Assert Setup Exercise Verify Teardown
База
База Поддельная база
База Поддельная база SQLite
База Поддельная база SQLite Настоящая база
База Поддельная база SQLite Настоящая база Test::DBIx::Class
Fixtures
Fixtures Копия реальной базы
Fixtures Копия реальной базы Слепок реальной базы
Fixtures Копия реальной базы Слепок реальной базы Искусственно подготовленный слепок
Fixtures Копия реальной базы Слепок реальной базы Искусственно подготовленный слепок
Пустая база
Fixtures Копия реальной базы Слепок реальной базы Искусственно подготовленный слепок
Пустая база Фабрики
package MR::Go::Admin::UserFactory; use base qw(DBIx::Class::Factory); __PACKAGE__->resultset(MR::Go::Admin:: Schema->resultset('User')); __PACKAGE__->fields({ name =>
__PACKAGE__->seq(sub {'User #' . shift}), city => __PACKAGE__->related_factory('MR::Go::Admin::CityFactory'), status => 'new', }); DBIx::Class::Factory
package MR::Go::Admin::UserFactory; use base qw(DBIx::Class::Factory); __PACKAGE__->resultset(MR::Go::Admin:: Schema->resultset('User')); __PACKAGE__->fields({ name =>
__PACKAGE__->seq(sub {'User #' . shift}), city => __PACKAGE__->related_factory('MR::Go::Admin::CityFactory'), status => 'new', }); https://goo.gl/tBIRwZ DBIx::Class::Factory
Фабрика в деле sub set_status : Test(1) { my ($self)
= @_; my $task = MR::Admin::Go::Test::Factory::Task->create(); $task->set_status('TEST_NEW_STATUS'); is($task->status, 'TEST_NEW_STATUS', 'status'); return; }
Транзакции
Транзакции setup = BEGIN
Транзакции setup = BEGIN teardown = ROLLBACK
Транзакции setup = BEGIN teardown = ROLLBACK $self->break_db();
Test doubles
Test doubles Mock
Test doubles Mock Spy
Test doubles Mock Spy Stub
Test doubles Mock Spy Stub Dummy
Моки с магией my $mock = Test::MockModule->new('MR::Go::Admin::SMS'); my $sent =
0; $mock->mock(_send => sub { $sent = 1 });
Моки с магией local *MR::Go::Admin::SMS::_send = sub { $sent++ };
my $mock = Test::MockModule->new('MR::Go::Admin::SMS'); my $sent = 0; $mock->mock(_send => sub { $sent = 1 });
Моки без магии package MR::Go::Admin::User::Test::_FakeUser; MR::Go::Admin::User::Test::_FakeUser->new(); bless $user, 'MR::Go::Admin::User::Test::_FakeUser';
Моки без магии has _logger => (default => sub {
'...' }); User->new({_logger => $fake_logger}); User->new({_message_size_limit => 42}); package MR::Go::Admin::User::Test::_FakeUser; MR::Go::Admin::User::Test::_FakeUser->new(); bless $user, 'MR::Go::Admin::User::Test::_FakeUser';
Asserts is($node->children->count, 0, 'leaf node');
Asserts is($node->children->count, 0, 'leaf node'); is($rating, 42); cmp_ok($status, 'eq', 'processed');
ok($user->deleted);
is($node->children->count, 0, 'leaf node'); is($rating, 42); cmp_ok($status, 'eq', 'processed'); ok($user->deleted);
Asserts use Test::Deep;
cmp_deeply( $users, bag($user1, $user2) ); cmp_deeply( $user, methods( rating =>
42, blocked => bool(0), ) ); Test::Deep
Спасибо Вадим Пуштаев
[email protected]
https://goo.gl/SNrhWp Дизайн Максим Гелета
Бонус: ExportCatcher { package MR:Go::Admin::Test::_ExportCatcher; use MR::Go::Admin::Schema; use Test::DBIx::Class; }