Mobile Factory Tech Blog

技術好きな方へ!モバイルファクトリーのエンジニアたちが楽しい技術話をお届けします!

Perlのテストモジュールの紹介

この記事は、モバイルファクトリーAdvent Calendar 2018 23日目の記事です。
前日の記事は、id:masasuzさんの モバイルファクトリーのインフラアーキテクチャ でした。

こんにちは、id:yumlonneです!
最近、テストの重要性をひしひしと感じているので、テストについての記事を書くことにしました。

他の記事でも紹介されていますが、モバイルファクトリーの主要プログラミング言語はPerlです。
Perlは動的型付け言語であり、プログラマがデータ型を管理しなければならないため、非常にテストが重要です。

今回は、最近個人的に注目しているテストモジュールを2つ紹介します。

Test::Doctest

Test::Doctestは、Python由来のテストモジュールです。
その名の通り、ドキュメント内にテストを仕込むことができます。

ここでいうドキュメントとは、平たく表現すれば「ソースコード内の関数説明などに用いられるコメント」のことです。
Perlでは#を使ってコメントを書くことができますが、関数説明にはPODを使います。

Test::Doctestは、POD内に埋め込まれたテストを実行します。

使用例

コード

pod内の>>>の後ろにコードを書き、下の行に期待する結果を書きます。

package Hoge;
use strict;
use warnings;
use utf8;

=encoding utf8

=head1 METHODS

=over

=item plus1

    数値に1を足してくれる関数

    >>> plus1(30)
    31

    >>> plus1(-1)
    0

=back

=cut
sub plus1 {
    my $n = shift;
    return $n + 1;
}

1;

テスト

コマンドラインからテストを実行する例を載せますが、.tファイルにすることもできます。
詳細はSYNOPSISを参照してください。

$ perl -MTest::Doctest -e run lib/Hoge.pm
1..2
ok 1 - plus1 1/2 (lib/Hoge.pm, 16)
ok 2 - plus1 2/2 (lib/Hoge.pm, 19)

Test::Doctestまとめ

以下に私なりの長所・短所をまとめました。
短所を認識し、複雑なものは別のファイルに書くなどの対応をすれば、十分に使う価値のあるモジュールだと思います。

長所

  • ソースコードと同一のファイルにテストが書けるため、敷居が低い
  • 関数の入出力例を示すことができる
  • DoctestのためにPODを書くというモチベーションが生まれる

短所

  • 複雑な関数や文字列での表現が難しい(あるいは長くなる)入出力データを扱うのが難しい
  • 書きすぎるとソースコードの見通しが悪くなる

Test::RandomCheck

Test::RandomCheckは、Haskell由来のテストモジュールです。
このテストモジュールには大きな特徴が2つあります。

  • テストデータをモジュールがランダムに生成する
  • テストするのは関数の性質

使い所は限られていますが、非常に簡単にテストができます。

使用例

コード

ここでも先程テストしたplus1関数のテストをします。

package Hoge;
use strict;
use warnings;
use utf8;

sub plus1 {
    my $n = shift;
    return $n + 1;
}

1;

テスト

use Test::RandomCheck;
use Test::RandomCheck::Generator;
use Test::More;

use Hoge;

# 受け取りたい引数の型
my $arg_type = integer;

random_ok {
    # ここでinteger型の値を受け取れる
    my $arg = shift;

    # plus1の性質をチェック
    Hoge::plus1($arg) == $arg + 1;
} $arg_type;

done_testing;

テスト結果

$ perl -Ilib t/randomcheck,t
ok 1
1..1

テストの結果の出力は非常に寂しいものの、この例ではrandom_okブロックは様々な整数値で202回実行されていました。

Test::RandomCheckまとめ

以下に私なりの長所・短所をまとめました。
使い所は難しいですが、うまく使えればとてもパワフルなモジュールだと思います!

長所

  • テストデータを考える作業をスキップできる
  • 関数が持つ性質を表明できる(reverseした配列をreverseするともとに戻るなど)

短所

  • 実験的なモジュールである
  • テストデータがランダムであるため、失敗したテストケースの特定が難しい(Haskellではテストデータを再現できる)
  • 汎用的な関数以外はテストしにくい

おわりに

今回はPerlのテストモジュールを2つ紹介しました。
テストを充実させるために、まずはテストを楽しむことが重要だと思っています。
皆さんもぜひ、紹介したテストモジュールなどを使って、テストを楽しんでみてはいかがでしょうか!

明日はid:Carimaticsさんです。お楽しみに!!

モバイルファクトリーのインフラアーキテクチャ

この記事はモバイルファクトリー Advent Calendar 2018の22日目のものです。 このブログではお初にお目にかかります。インフラチームのid:masasuzです。

モバイルファクトリーでは現在AWSと物理データセンターを使用しています。 モバイルファクトリーではもともと物理データセンター使用しており、既存のサービスはその上で構築されております。 数年前からAWSを本格的に利用し始めて新規のサービスは基本的にAWSで構築します。 AWSで構築されたサービスは要件によって様々なアーキテクチャになっています。

今回はある程度共通化されている物理データセンターにあるサービスのインフラアーキテクチャについて述べていきます。

アーキテクチャ

  • リバースプロキシ
    • Nginx
  • アプリケーションサーバ
    • Plack/PSGIサーバ(Starlet, Gazelle) + Server::Starter
  • 静的コンテンツサーバ
    • Nginx + CDN
    • Amazon S3
  • ストレージサーバ
    • MySQL(or Percona Server)
    • Redis
  • キャッシュサーバ
    • Memcached
    • Redis
  • ジョブキューサーバ
    • Gearman
    • Qudo
    • Resque

個々のミドルウェアは置いておいて、構成としては特別なものを使っていないと思います。 モバイルファクトリーとして特色のあるアプレケーションサーバに関して少しだけ詳しく述べたいと思います。

サーバ全般

サーバOSはLinuxを使っており、ディストリビューションとしてはUbuntu Serverを使用しています。かつてはDebianを使用していましたが、全て置き換えられています。 ミドルウェアは可能な限り標準のインストールで入るものを使用します。

標準でパッケージが用意されていない場合はdebパッケージを作成して、社内のaptサーバからインストールできるようにしています。 サーバ構築毎にビルドするということはしないようにしています。

つまり何かインストールするときは基本的にaptitude installないしapt-get installですむようになってます。

Perl

モバイルファクトリー で作られているプロダクトは最近は別として、ここ10年くらいはPerlで書かれています。

かつてはOS標準についてくるSystem Perlを利用していましたが、

  • OSアップグレードのたびにバージョン変わるのはつらい
  • 新しいバージョンのPerlを使いたい

などの理由で、独自にパッケージングしたperlを使うようにしています。

mf-perl5.xxの名前でパッケージングしてプロジェクト側で使いたいバージョンのperlを選択できるようにしています。

Perlモジュール

Perlモジュールのバージョン管理に関しては、cpanfile.snapshotを元にcarton install --deploymentでインストールすることにより、 依存パッケージも含めて同じバージョンのPerlモジュールがインストールされるようになっています。

基本的には公開されているCPANのモジュールを使うようにしていますし、それが推奨されてますが、 社外に公開できないロジックが含まれていたりするものに関してはdarkpan(プライベートなCPANレポジトリ)を立ててそこからインストールするようにしています。

アプリケーションサーバ

かつてはApache + mod_perlで動いていましたが、公開されているサービスは全てPlack/PSGIに置き換えられています

アプリケーションサーバのデーモン管理にSystemdを利用しています。これもOS標準の起動方法に合わせるためです。 Start::Server経由でPlack/PSGIサーバを起動することにより、ホットデプロイできるようにしています。

アプリケーションサーバとしては主にStarletを使っていますが、新しめのプロジェクトではGazelleも使われています。

WebフレームワークとしてはSledge、Splite、Amon2が使われています。SpliteはPSGI対応したSledge風のフレームワークです。 社内独自フレームワークです。 SledgeやSpliteは長めに運営されているサービスで使われており、現在では新規でPerlのプロジェクトを作る場合は、Amon2が使われております。

結びに

モバイルファクトリーで主に使われているアーキテクチャについてざっくりと書いてきました。これは現在の姿で、課題があれば日々変化していっています。 一昔前であれば、デーモン管理はUpstartを使っていましたし、リバースプロキシはPerlbalを使っていました。 長年運営しているサービスもあるので、ドラスティックに変更はできませんが、少しずつよりよい形に改善していってます。

また、冒頭で述べたように新規のサービスではAWSで構築することが多く、AWSに合わせたアーキテクチャを構築しています。 これに関してはどこか別のところで述べられたらと思います。

また、今回はざっくりでしたが、掘り下げて知りたいこと等ありましたら、またどこかの機会で述べたいと思います。

明日は、id:yumlonne さんです。