LoginSignup
1
1

More than 5 years have passed since last update.

Perlにもunittest.mockが欲しい

Posted at
1 / 12

これはなに?

  • 2019-01-25 の YAPC::Tokyo 前夜祭のLTで使ったスライド
  • ネタ画像などを抜いたもの
  • 旧題「行動してから主張せよ」

Python の unittest.mock

  • 2008年に誕生
  • Python 3.3 でビルトインに
  • record -> replay より action -> assertion

record -> replay

# record
mocker = Mocker()
mock = mocker.mock()
mock.get("https://haskell.jp")
mocker.result(Response())

client = Client()
client.agent = mock

# replay
mocker.replay()
res = client.call_api("https://haskell.jp")

mocker.restore()
mocker.verify()

record -> replay

  • テスト結果を先に記述する必要がある
  • 動作後にも検証が必要なので、検証コードが分かれる

action -> assertion

client = Client()
client.agent = mock.Mock()

# action
res = client.call_api("https://haskell.jp")

# assertion
client.agent.get.assert_called_with("https://haskell.jp")

action -> assertion

  • 動作させ、その結果を検証するという流れ
  • 通常の単体テストの流れと合致する

Perlで実装したい


テストしたいコード

sub test_code {
    my $dbh = DBI->connect(
        "DBI:mysql:yapc:localhost", "tokyo", "oykot");
    my $sth = $dbh->prepare("SELECT name, age FROM atendee");
    $sth->execute;

    my $atendee = $sth->fetchrow_hashref;
    printf "%s (%d)\n", $atendee->{name}, $atendee->{age};
}

テストコード

patch_sub {
    my $mock = shift;
    # action
    test_code;

    # assertion
    $mock->lazymock_called_with_ok(
        prepare => ["SELECT name, age FROM atendee"]);
} 'DBI::connect';

test_code より以下が出力される。

Test::LazyMock=REF(0x7fea9f0f25b0) (1)

呼出履歴の表示

print "$_->[0]\n" for $mock->lazymock_calls;
prepare
prepare->execute
prepare->fetchrow_hashref
prepare->fetchrow_hashref->{name}
prepare->fetchrow_hashref->{name}->`""`
prepare->fetchrow_hashref->{age}
prepare->fetchrow_hashref->{age}->`0+`

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1