Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9409

受信メールの検証、MailTrap

$
0
0
概要 以前、投稿した記事「CodeceptJSで受信メールの検証、MailSlurp vs gmail お薦めはMailSlurp」に利用できるメールサーバを1つ追加という話。 まず簡単に、前回紹介したものも含めて比較してみます。 メール受信 必要なインストール 受信手段 利用するメールサーバ 特記事項 MailTrap 特になし APIを参考に自作したLastMail受信メソッド MailTrap 1つのinboxに50通まで。その後は古いメールから削除される。無料だと500通/月まで MailSlurp MailSlurp-client メールがこちらに送信された後のLastMailメソッド MailSlurp 利用頻度によっては有料プランが必要。無料だと100通/月まで gmail inboxおよびmailParserおよびiconv メール待受け中の着信に反応 gmail IMAPが必須。gmailの外からのアプリケーションアクセスの許可が必須 参考にした資料: メールのテストに便利なMailTrap Mailtrap API Documentation e2eテスト自動化する 専用のメール・クライアントが用意されている「MailSlurp」 APIを参考に自前でゴリゴリ受信メソッドを書く「MailTrap」 一言で言うと、そんな感じです。 MailSlurpとMailTrapの有料プランを比較してみました。参考まで。 MailSlurp MailTrap MailTrapは9ドルからあるみたいです。あと、inboxの数に違いがありますが、メールアドレスにエイリアスを使わなければ、inboxの数 = テストに使えるメールアドレスの数、と考えると、同じくらいの料金ではMailSlurpの方が多いように見えます。 また、MailSlurp-clientでは、開発言語についてjavaScript のみのようですが、MailTrapでは、cURLといったCUI、Ruby / Python / PHP / Java / Perl / C# についてもスニペットがありますので、自作に当たっての参考になればと思います。 メール受信して何を自動テストするか メールを受信して、本文に含まれるキーワードを使ってWebUIの検証をするという点は前回の投稿と同等ですが、メールのSubjectについて検証対象に追加しました。 Selenium学習サイトを使って、以下のメール本文 [会員ランク] [会員氏名]様。 この度は当ホテルに会員登録いただき、誠にありがとうございました。 登録手続きが完了いたしましたので、ご連絡申し上げます。 ユーザーID:[メールアドレス] パスワードは登録時に設定頂いたものをお使い頂けます。 ご登録頂いた内容につきましては、以下のアドレスにてご確認頂けます。 [URL] それでは、ご利用を心からお待ち申し上げております。 [トップページのURL] からメールアドレスと控えておいたパスワードを使って、会員情報へのログインした後、IDと会員ランクと氏名とを評価します。 今回も、テストデータとして以下を準備して臨みました。 登録済みの4名を使ったテスト(会員登録完了のご連絡001 / 会員登録完了のご連絡006 / 会員登録完了のご連絡007/ 会員登録完了のご連絡008) リンク先URLが間違っているケース(会員登録完了のご連絡002) 会員種別が間違っているケース(会員登録完了のご連絡003) メール文言の一部が間違っているケース(会員登録完了のご連絡004) 会員氏名が間違っているケース(会員登録完了のご連絡005) メール本文さえ取得できれば、後はURLっぽいのを抽出したり、メールアドレスっぽいのを抽出したりは、JavaScriptのmatch関数で正規表現を用いて行ないます。 .waitForLatestEmail だけでメール本文を取得できる点でMailSlurpは、とても簡単です。 今回紹介するMailTrapの場合、API仕様に従ったhttpsリクエストを投げて返信をもらうといった実装は、自前で行なう必要があります。 メールに記載のURLに移動したり、ログインをしたりは、CodeceptJSを利用します。 MailTrapを利用した場合の自動テスト環境設定について 事前にMailTrapのサイトにアカウントを作成しログイン後、Api-Tokenを取得しておきます。 また、IDおよびパスワードも画面に表示されたものを使いますので控えておきます。 inboxid(受信箱のIDみたいなもの)は、APIのドキュメントページにてApi-Tokenを使って取得します。 このAPIドキュメントですが、実際にhttpsでリクエストを出して、返信を確認することが出来ますので、テストコードを実装する際、挙動を確認しながらの作業ができます。 受信するinboxのメールアドレスは、 InboxのEmail Addressタブに表示されたものを利用します。 codecept.conf.jsですが、helperにcodeceptjs-chai、plugINにAllureレポートを追加しただけで、MailTrapに関するものは、何も追加しません。 メール送受信に関するコードは、 eMailMailTrapCommon.js var nodemailer = require('nodemailer'); module.exports.SendMail = async function(rank, subject, simei, id, url, callback_func){ var address = 'ここにMailTrapの受信ボックスアドレス'; var nodemailer = require('nodemailer'); var smtpConfig = { port: 2525, host: 'smtp.mailtrap.io', auth: { user: 'ここにMailTrapのID', pass: 'ここにMailTrapのパスワード' } }; const transporter = nodemailer.createTransport(smtpConfig); var body01 = '様。\r\n'; var body02 = 'この度は当ホテルに会員登録いただき、誠にありがとうございました。\r\n'; var body03 = '登録手続きが完了いたしましたので、ご連絡申し上げます。\r\n'; var body04 = 'ユーザーID:'; var body05 = 'パスワードは登録時に設定頂いたものをお使い頂けます。\r\n'; var body06 = 'ご登録頂いた内容につきましては、以下のアドレスにてご確認頂けます。\r\n'; var body07 = 'それでは、ご利用を心からお待ち申し上げております。\r\nhttps://hotel.testplanisphere.dev/ja/index.html'; var body = rank + '\r\n' + simei + body01 + body02 + body03 + body04 + id + '\r\n' + body05 + body06 + url + '\r\n' + body07; let info = await transporter.sendMail({ from: 'ここは送信元のアドレス', to: address, subject: subject, text: body }, function(e, res){ console.log(e ? e.message : res.message); smtp.close(); }); return await info; }; module.exports.lastMailId = async function(){ var result; var https = require('https'); var url = 'https://mailtrap.io/api/v1/inboxes/"ここにinboxid"/messages'; let options = { headers: { 'Api-Token': 'ここにApi-Token' } } var data = []; let promise = await new Promise(async(resolve, reject) => { await https.get(url, options, async function (res) { await res.on('data', function(chunk) { data.push(chunk); }).on('end', function() { var events = Buffer.concat(data); var r = JSON.parse(events); var matchData = r.filter(function(item, index){ if(item.id != '0') return true; }); resolve(r[0].id); // console.log(r[0].id); }); }); }).then((lastId) => { result = lastId; }); return await result; } module.exports.receiveSubject = async function(){ var result; var https = require('https'); var url = 'https://mailtrap.io/api/v1/inboxes/"ここにinboxid"/messages'; let options = { headers: { 'Api-Token': 'ここにApi-Token' } } var data = []; let promise = await new Promise(async(resolve, reject) => { await https.get(url, options, async function (res) { await res.on('data', function(chunk) { data.push(chunk); }).on('end', function() { var events = Buffer.concat(data); var r = JSON.parse(events); var matchData = r.filter(function(item, index){ if(item.id != '0') return true; }); resolve(r[0].subject); // console.log(r[0].id); }); }); }).then((lastId) => { result = lastId; }); return await result; } module.exports.receiveMail = async function(mailid){ var result; var https = require('https'); var url = 'https://mailtrap.io/api/v1/inboxes/"ここにinboxid"/messages/' + mailid + '/body.txt'; let options = { headers: { 'Api-Token': 'ここにApi-Token' } } var data = []; let promise = await new Promise((resolve, reject) => { let client = https.get(url, options, function (res) { res.setEncoding('utf-8'); res.on('data', function(chunk) { resolve(chunk); }); res.on('close', function(){ // console.log('Connection closed'); }); res.on('end', function() { // console.log('Response data end'); }); res.on('aborted', function() { console.log('Connection aborted'); }); }); }).then((body) => { result = body; }); return await result; }; Node.jsのhttpsモジュールでApi-Token含めてGETし、返信がJSON形式で返ってくるので、最後に着信したメールのIDを取得し、取得したメールIDの本文をUTF-8でエンコードして取り出しています。 MailSlurp-clientの .waitLastEmailは未読の最終着信を見ているようなので、ここは、もう少し(例えばメールが到着しない場合とか想定して)改良の余地があるかもしれません。 CodeceptJSで使うテストコードは、以下のようになります。 eMailTest_test.js let emailTestTable = new DataTable(['Subject', 'url', 'verifyTitle', 'verifyWord', '会員ランク', '会員氏名', '会員ID', '会員Pass']); emailTestTable.add(['会員登録完了のご連絡001','https://hotel.testplanisphere.dev/ja/login.html','ログイン | HOTEL PLANISPHERE - テスト自動化練習サイト','ご利用を心からお待ち申し上げております。', 'プレミアム会員', '山田一郎', 'ichiro@example.com', 'password']); emailTestTable.add(['会員登録完了のご連絡002','https://hotel.testplanisphere.dev/ja/index.html','ログイン | HOTEL PLANISPHERE - テスト自動化練習サイト','ご利用を心からお待ち申し上げております。', 'プレミアム会員', '山田一郎', 'ichiro@example.com', 'password']); emailTestTable.add(['会員登録完了のご連絡003','https://hotel.testplanisphere.dev/ja/login.html','ログイン | HOTEL PLANISPHERE - テスト自動化練習サイト','ご利用を心からお待ち申し上げております。', '一般会員', '山田一郎', 'ichiro@example.com', 'password']); emailTestTable.add(['会員登録完了のご連絡004','https://hotel.testplanisphere.dev/ja/login.html','ログイン | HOTEL PLANISPHERE - テスト自動化練習サイト','ご利用を心からお待ち申し上げます。', 'プレミアム会員', '山田一郎', 'ichiro@example.com', 'password']); emailTestTable.add(['会員登録完了のご連絡005','https://hotel.testplanisphere.dev/ja/login.html','ログイン | HOTEL PLANISPHERE - テスト自動化練習サイト','ご利用を心からお待ち申し上げております。', 'プレミアム会員', '山田一朗', 'ichiro@example.com', 'password']); emailTestTable.add(['会員登録完了のご連絡006','https://hotel.testplanisphere.dev/ja/login.html','ログイン | HOTEL PLANISPHERE - テスト自動化練習サイト','ご利用を心からお待ち申し上げております。', '一般会員', '松本さくら', 'sakura@example.com', 'pass1234']); emailTestTable.add(['会員登録完了のご連絡007','https://hotel.testplanisphere.dev/ja/login.html','ログイン | HOTEL PLANISPHERE - テスト自動化練習サイト','ご利用を心からお待ち申し上げております。', 'プレミアム会員', '林潤', 'jun@example.com', 'pa55w0rd!']); emailTestTable.add(['会員登録完了のご連絡008','https://hotel.testplanisphere.dev/ja/login.html','ログイン | HOTEL PLANISPHERE - テスト自動化練習サイト','ご利用を心からお待ち申し上げております。', '一般会員', '木村良樹', 'yoshiki@example.com', 'pass-pass']); Feature('emailTest'); Data(emailTestTable).Scenario('eMail_Test', async ({I , current}) => { var mailBox = require('../emailMailTrapCommon'); //テスト用メール送信 var sendMail = await mailBox.SendMail(current.会員ランク,current.Subject,current.会員氏名,current.会員ID,current.url,null); await sleep(10000); // I.wait(30); //ここまで var lastid = await mailBox.lastMailId(); var sentSubject = await mailBox.receiveSubject(lastid); var sentBody = await mailBox.receiveMail(lastid); console.log(sentSubject); console.log(sentBody); //Subjectの検証 I.assertContain(sentSubject, current.Subject); //文面の文言検証 I.assertContain(sentBody, current.verifyWord); const memberid = await sentBody.match(/[A-Za-z0-9_.-]*@example.com/)[0]; const url = await sentBody.match(/(https?|ftp)(:\/\/[\w\/:%#\$&\?\(\)~\.=\+\-]+)/g)[0]; //文面から取得したURLに移動 await I.amOnPage(url); //移動先の検証、ここではタイトル I.seeTitleEquals(current.verifyTitle); //文面から取得したアカウントでログイン I.fillField('email', memberid); I.fillField('password', current.会員Pass); I.waitForClickable('#login-button'); I.click('#login-button'); //文面から移動した会員ページの検証 I.see(current.会員ID); I.see(current.会員氏名); I.see(current.会員ランク); I.click('#logout-form > button'); }); function sleep(time) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, time); }); } 前述した意図的にエラーを混入させたテストデータを含めて、8件のテストが実行されます。 Subjectの検証ですが、テストデータに含まれるSubjectを、そのままメール送信しているので、本件ではメール受信した後の検証でエラーにはならず、会員ページに記載の氏名と異なっていると検出されています。実際のメール送信を含むシステムテストでは、期待されるSubject(例えば予約日付が入ったり)を含むテストデータを準備してテストに臨むことになります。 メールテスト中は、I.wait()が効いていなさそうなので、別途 sleep を実装して使っています。 テスト結果の確認 メールボックスには、テスト用のメールが着信していることが確認できます。 テストレポートはAllureで表示できます。 余談ですが、今回helperとしてplayWrightを用いて、テスト中の動画撮影機能を有効化してみました。 撮影された動画は、エラーを混入したテストデータを使った場合のみ、個別にクリップとして記録されているようです。Allureのレポートに表示されるスクリーンショットと併せて、動画も記録として残るようなので(platWrightの場合だけです。また、webm形式で記録されます。)報告資料として添付する等の用途があるかと思います。 総括 前回のMailSlurpに続いてMailTrapについてもメール受信のテストで使えますので、メール受信が関係するWebUIの自動テストの事例紹介とします。 紹介した事例にあるように、メールのSubjectと本文が、間違っていないかのテストが主旨となります。仕様との差異を間違い探しするようなことです。( 一郎 と 一朗 みたいな) 単に間違い探しであれば、あまり予算や時間をかけずにできる点で、MailSlurpやMailTrapを利用して、CodeceptJSと併用するのは、良い選択だと考えます。 ぜひ、やってみてください。

Viewing all articles
Browse latest Browse all 9409

Trending Articles