Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
MR::Go::Admin::Test
Search
Vadim Pushtaev
January 23, 2017
Programming
98
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
MR::Go::Admin::Test
Vadim Pushtaev
January 23, 2017
More Decks by Vadim Pushtaev
See All by Vadim Pushtaev
PyCon Russia 2018 — Unit Testing
vadimpushtaev
0
440
Perl course (5), testing
vadimpushtaev
0
130
Perl course (4), testing
vadimpushtaev
0
130
Perl course (4), db
vadimpushtaev
0
240
Perl course (4), oop
vadimpushtaev
1
200
Perl course (4), mod
vadimpushtaev
0
210
Perl course (3), testing
vadimpushtaev
0
110
Perl course (3), db
vadimpushtaev
0
97
Perl course (3), oop
vadimpushtaev
0
120
Other Decks in Programming
See All in Programming
フロントエンドUIフレームワークのこれまでとこれから
ssssota
1
800
Webの地図
yosuke_furukawa
PRO
3
1.5k
初心者DevRelとして参加者だった私が、DevRel Talks!#2に登壇するまでにしてきたこと
sokohirai
0
340
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
180
「AI時代、配布するPythonコードをどう守るか: 難読化の実験と判断軸」 #PyconJP2026
pkshadeck
PRO
2
180
まだ間に合う!今年の夏こそSchemeのマクロ展開器を完全理解!
omasanori
0
640
Go × SIMDで高速化するベクトル検索 ~ルーフラインモデルでSIMDが効く境界を探れ! ~
po3rin
1
160
30年振りにコンパイラの定数整数除算を改善した
herumi
9
4.5k
go-spidermonkeyでAIエージェントのCode Modeを実装する
syumai
3
1.5k
新人はどこまで自力でやり、どこからAIに頼るべきか/エンジニア育成に向き合う_先輩たちの悩みと知見共有会
toppan_digital_dev
1
580
信頼性の目標を誰も求めてない
shubox
0
490
AI に Inclusive UI を書かせよう — Design Rules Skill で Compose UI を作り直す
theoriatec2024
1
460
Featured
See All Featured
WCS-LA-2024
lcolladotor
0
820
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.6k
Side Projects
sachag
455
43k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
970
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
430
Heart Work Chapter 1 - Part 1
lfama
PRO
8
36k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
190
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
The Cult of Friendly URLs
andyhume
79
7k
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; }