mochaとsuperagentでexpressを使ったサービスのログイン周りのテストすた2012年10月29日

このエントリーをはてなブックマークに追加
はてなブックマーク - mochaとsuperagentでexpressを使ったサービスのログイン周りのテスト

前回のexpress+soket.ioでのセッション管理に続いて、今回はexpressのセッション管理のテストについて。

mochasuperagentを使えば

  • ページの表示確認(ステータスコード・ページbody本文)
  • ログインページヘのpostで正しくログイン出来るか
  • ログイン状態管理(セッションでの振り分けが出来ているか・リダイレクトが正しく行われているか)
などのログイン周りのテストが簡単に出来るようなので試してみました。

ソースコードとサンプル

コード
mochaとsuperagentを用いてexpressのアプリのログイン周りのテスト — Gist
.
├── app.js
├── chat.html
├── index.html
├── node_modules
│   ├── connect-redis
│   ├── cookie
│   ├── ejs
│   ├── express
│   ├── should
│   ├── socket.io
│   └── superagent
├── package.json
└── test
     ├── app.test.js
     └── mocha.opts


テスト対象の動作サンプル
Socket.io-Express3.0.0rc3 session sample
簡単なチャット。passwordがtestなら何でもログイン可能。やけに時間がかかるのはherokuだから?


やったこと

インストール

npm install mocha
npm install superagent
npm install should
shouldもとりあえず。
mochaについてはテストフレームワーク mocha – hokaccha.hamalog v2がとても参考になりました。

app.js側の準備

基本的に前回とほとんど同じですが、expressの設定とsessionStoreをテストコードから参照するために2行ほど書き換えます。
var app = module.exports = express();
app.configure(function() {
    //テスト用
    app.set("sessionStore",sessionStore);
});


ログインが必要なページのテスト

まず、/chatにアクセスするためにはログインが必要。
ログイン前に直接アクセスすると/にリダイレクトされるはずです。そのテストを行うコードは次のようになります。
var url = require('url')
  , should = require('should')
  , assert = require('assert')
  , superagent = require('superagent');

describe('HTTP Server Test', function() {
    //テストに使用するユーザーを作成
    var testUser = superagent.agent();
    
    it('ログイン前にチャットページにアクセスしたらログインページにリダイレクトされるはず', function(done) {
        testUser.get('http://localhost:3000/chat').end(function(err, res) {
            should.not.exist(err);
            res.redirects.should.not.be.empty;
            should.equal(url.parse(res.redirects[0], false, true).pathname, "/");
            done();
        });
    });
});
superagent.agent()でユーザーを作成して、
getでHTTP GETの要求を/chatにした後リダイレクト先が/であることを確かめています。

testディレクトリにapp.test.jsなどという名前で保存してmochaを実行すれば
$ mocha
   info  - socket.io started

  ․

  ✔ 1 test complete (17ms)
などと表示され無事にテストが通ったことが分かります。

ログイン処理のテスト

次に、/ページではログインを行います。
ログインフォームは
<form action="/user/login" method="post">
    ID: <input type="text"  name="userID" value="test"/> <br/>
    PASS: <input type="text"  name="password" value ="test"/>
    <input type="submit" value="login" />
</form>
postを受け付ける部分は
//ログイン処理
app.post('/user/login', function(req, res) {
    var postData = {
        userID : req.body.userID,
        password : req.body.password
    };
    //passがtestならログイン成功させる
    if ( typeof postData.userID !== 'undefined' && typeof postData.password !== 'undefined' && postData.password.toString() === 'test') {
        //sessionにユーザーID保存
        req.session.userID = postData.userID.toString();
        res.redirect('/chat');
    }
    else {
        console.log('login failed');
        res.redirect('/');
    }
});
のようになっていて、/user/loginにHTTP POSTでuserID, passwordを送るようになっています。

superagentではユーザーごとのcookieの管理が出来るため、セッション管理のテストもできます。
このログイン処理のテストを行うコードをmocha+superagentで書くと以下のように。
describe('HTTP Server Test', function() {
    //テストに使用するユーザーを作成
    var testUser = superagent.agent();  //正規にログインするユーザー
    var invalidUser = superagent.agent(); //ログインしないユーザー

    it('ログインに成功したら/chatにリダイレクトされるはず', function(done) {
        //ログインページに対してのPOST送信でログイン処理を行う
        testUser.post('http://localhost:3000/user/login').send({
            userID : 'test',
            password : 'test'
        }).end(function(err, res) {
            should.not.exist(err);
            res.redirects.should.not.be.empty;
            should.equal(url.parse(res.redirects[0], false, true).pathname, "/chat"); 
            done();
        });
    });

    it('ログイン済みのtestUserは/chatに直接アクセスすると/chatにアクセスできるはず', function(done) {
        testUser.get('http://localhost:3000/chat').end(function(err, res) {
            should.not.exist(err);

            //ページが表示され、それは/chatなはず
            should.equal(res.statusCode, 200);
            should.equal(res.req.path, "/chat");
            done();
        });
    });

    it('ログインしてないinvalidUserは/chatに直接にしても/にリダイレクトされるはず', function(done) {
        invalidUser.get('http://localhost:3000/chat').end(function(err, res) {
            should.not.exist(err);

            //リダイレクト先が存在し、/にリダイレクトされるはず
            res.redirects.should.not.be.empty;
            should.equal(url.parse(res.redirects[0], false, true).pathname, "/");
            done();
        });
    });
});

testUserとinvalidUserの2ユーザーを作り、testUserは.post(‘user/login’).send({userID : ‘test’,password : ‘test’})でログイン処理を。
testUserはログイン済みのため/chatにアクセスできますが、invalidUserは未ログインなため/にリダイレクトされます。

セッションストアにデータが収められているかのテスト

最後に、sessionStoreに正しくセッション情報が保存されているかどうかのテスト。
ヘッダのcookieからセッションIDを取り出して、それを元にセッションストアからセッションデータを取り出してユーザー名を確かめます。
これはsocket.ioの認証時にも同じ事をしています。

var url = require('url')
  , connect = require("express/node_modules/connect")
  , should = require('should')
  , assert = require('assert')
  , superagent = require('superagent')
  , app = require('../app.js');


describe('HTTP Server Test', function() {
    //テストに使用するユーザーを作成
    var testUser = superagent.agent();

    it('ログインに成功したらセッションストレージにユーザー名が保存されているはず', function(done) {
        testUser.post('http://localhost:3000/user/login').send({
            userID : 'test',
            password : 'test'
        }).end(function(err, res) {
            should.not.exist(err);
            
            //sessionStoreにsessionデータが保存されているはず
            var header_cookie = res.req._headers.cookie;
            var cookie = require('cookie').parse(decodeURIComponent(header_cookie));
            cookie = connect.utils.parseSignedCookies(cookie, app.get('secretKey'));
            var sessionID = cookie[app.get('cookieSessionKey')];
            
            app.get("sessionStore").get(sessionID,function(err,session){
                 should.not.exist(err);
                 
                 //userIDがログイン時のものと一致するはず
                 should.equal(session.userID,"test");
                 done();
            });
        });
    });
});
sessionStoreにセッション情報が保存されていることを確認。

と、いうことで、mocha+superagentを使えばログイン処理まわりのテストも簡単に出来そうです!
superagentを使えば複数人の接続のテストも出来るかと!

今回のサンプルコードはここにまとめて置いておきました。
https://gist.github.com/3968061

このエントリーをはてなブックマークに追加
はてなブックマーク - mochaとsuperagentでexpressを使ったサービスのログイン周りのテスト

関連する記事

Leave a Reply

Dansette