テストを書けるようにしました

ちゃんとテンプレートに想定通りにデータが埋め込まれるか、確かめたい。

でもテストは自動化したいので、いちいちメール送信されるのは勘弁。

という事で、随分前に開発環境にはきむきむさんが作ってくれていたんですが、S2Mai用テストケースを追加したものをMavenのSNAPSHOTリポジトリに公開しました。

バージョンは0.9.4-SNAPSHOTです。まだこれからメソッド名など変更があるかも知れませんのでお試しの方はご了承下さい。

セットアップ

app.diconのincludeをこうします。

 <include condition="#ENV == 'ut'" path="s2mai_for_unit.dicon"/>
 <include condition="#ENV != 'ut'" path="s2mai.dicon"/>

この場合、ENVがutの場合はメール送信されません。

期待する本文の内容を書く

データ埋め込み済みとして期待される内容をテキストファイルとして保存します。保存先は、テストケースと同じパッケージにすると後々楽です。

例えばテンプレートがこうなら

TestMai_sendMail.ftl
 Subject: てすとまいです。
 
 ここからデータ。
 ${data.text}

こんな感じで。

TestMaiTest_expected.txt
 ここからデータ。
 埋め込みデータはこんな感じで。
 改行も入れてみるか。

拡張子はなんでもいいです。なくてもいいと思う。多分。

文字コードはmailProperties.diconで設定したtemplateEncodingの値に合わせて下さい。jarの中にある奴はUTF-8です。

改行コードは、テンプレートに合わせて下さい。

期待値としてテキストで書けるのは本文のみです。Subjectはテストケースの中で書きます。下記参照。

テストを書く

S2MaiTestCaseを使う場合と、任意のTestCaseクラスから呼び出す場合の2通りの方法があります。

S2MaiTestCaseを使う

S2MaiTestCaseは、S2TestCaseを継承してます。

 import org.seasar.mai.unit.S2MaiTestCase;
 import com.ozacc.mail.Mail;
 
 public class TestMaiTest extends S2MaiTestCase {
 
     private TestMai testMai;
     
     protected void setUp() throws Exception{
         include("app.dicon");
     }
     
     public void testメール送信(){
         TestMaiDto dto = new TestMaiDto();
         dto.setFrom("hoge@example.com");
         dto.setTo("fuga@foo.co.jp");
         dto.setText("埋め込みデータはこんな感じで。\r\n改行も入れてみるか。");
         
         testMai.sendMail(dto);
         
         Mail expected = new Mail();
         expected.setFrom("hoge@example.com");
         expected.addTo("fuga@foo.co.jp");
         String text = getTextFromFile("TestMaiTest_expected.txt");
         expected.setText(text);
         expected.setSubject("てすとまいです。");
         
         Mail actual = getActualMail(0);
         
         assertEquals(expected, actual);
         
     }
 
 }

期待値としてMailオブジェクトを作ります。本文を先程作った期待値テキストファイルから読み込みます。

 String text = getTextFromFile("TestMaiTest_expected.txt");
 expected.setText(text);

ファイル名を指定すれば、同じパッケージ内にあれば読み込みます。同じパッケージ内にない場合は、フルパスで書いて下さい(検証してないです・・・けど多分いける)。

Maiのメソッド実行の後に、S2MaiDtoを元に作ったMailオブジェクトを、getActualMail(int)で取得します。1つのテストメソッドの中でMaiのメソッドを複数回実行した場合、内部で生成したMailをリストで保持してますので、引数にインデックスを指定して取得して下さい。今回はメソッド呼び出し1回なので0を指定してます。

そして、取得した実行結果のMailオブジェクトと、期待値として作ったMailオブジェクトを、assertEquals(Mail, Mail)で比較出来ます。

内部では、それぞれtoString()して比較してます。

任意のTestCaseから使う

例えばS2TestCaseを継承したテストで同じ事をやってみます。SendMailTestUtilというユーティリティクラスを使います。

 public class TestMaiTest extends S2TestCase {
 
     private TestMai testMai;
     
     protected void setUp() throws Exception{
         include("app.dicon");
         SendMailTestUtil.init();
     }
     
     public void testメール送信(){
         TestMaiDto dto = new TestMaiDto();
         dto.setFrom("hoge@example.com");
         dto.setTo("fuga@foo.co.jp");
         dto.setText("埋め込みデータはこんな感じで。\r\n改行も入れてみるか。");
         
         testMai.sendMail(dto);
 
         Mail expected = new Mail();
         expected.setFrom("hoge@example.com");
         expected.addTo("fuga@foo.co.jp");
         String text = SendMailTestUtil.getTextFromFile(this, "TestMaiTest_expected.txt");
         expected.setText(text);
         expected.setSubject("てすとまいです。");
         
         Mail actual = SendMailTestUtil.getMail(0);
         
         assertEquals(expected.toString(), actual.toString());
         
     }
 
 }

setUp()の中で、SendMailTestUtil#init()を必ず実行して下さい。これで、保持しているMailがクリアされます。

本文の期待値は、

 String text = SendMailTestUtil.getTextFromFile(this, "TestMaiTest_expected.txt");

とやって取得します。thisを第1引数に指定する事で、同じパッケージ内のファイルを探しに行きます。

実行結果のMailオブジェクトは

 Mail actual = SendMailTestUtil.getMail(0);

とやって取得出来ます。

検証は、自前でそれぞれtoString()してやれば出来ます。

懸念事項

埋め込みデータ内の改行コードと、テンプレート・本文期待値テキストのそれが違ってくるとテストが通らないんだよなあ。

考えてるのは、改行コードをタイトに検証するか、改行されてればコードは問わないかを選べるようにするって方法。デフォルトはコード問わずにしたい。

あとメソッド名が不揃いな所が・・・変えちゃうかも。