SlackからSeleniumを起動して自動テストを行うようにした挑戦の備忘録

  • 16
    Like
  • 0
    Comment
More than 1 year has passed since last update.

「指定したテストをBOTに話しかけると、BOTがテスト実行してくれて、BOTからテスト結果が返ってくる」というようなプログラムを一回挑戦してみたいなと思い、やってみました。
環境はMacのOSXです。

環境構築

ローカルにHubotの導入

ありがたいことに、こんなにも分かりやすく書いてくださった方がいたので、その通りに作成。
SlackのBot(hubot)を作ってみる
作成自体は本当に簡単だなという印象です。

Node.jsでのSeleniumテスト環境を導入

これも、ありがたいことに、こんなにも分かりやすく書いてくださった方がいたので、その通りに作成しました。ICS Mediaさんにはお世話になりっぱなしで一度、菓子折りを持って行きたいくらいです。
Node.jsとSeleniumでWebアプリのUIテスト環境構築

HubotからSeleniumを起動させるようにする

いよいよ本題です。
hubot配下には以下のようなイメージでファイルを配置しました。
(説明がいらない部分のディレクトリやファイルについては記載していません。)

├── bin
├── node_modules
├── scripts
│   └── index.coffee
└── test
    ├── clickTest.js
    └── openTest.js

testディレクトリ内にはTestプログラムが入っており、bot側の処理に関してはindex.coffeeに記載しています。

メインとなるindex.coffeeのプログラムは、こんなカンジです。

index.coffee
module.exports = (robot) ->
  robot.respond '/.+/', (msg) ->
    @exec = require('child_process').exec
    #渡されたメッセージからテスト名を抽出し、ファイルパスを生成
    requestTxt = msg.match[0];
    testName = requestTxt.replace(/^@.+\s+/, "");
    filePath = "./test/#{testName}.js"
    #ファイルの探索をしてファイルがあればテスト実行し、無ければエラーを返す
    @exec "echo \"var fs = require('fs');fs.statSync('#{filePath}')\" | node", (error, stdout, stderr) ->
      msg.reply "#{testName}:No such Test file" if error?
      playTest filePath, msg if stdout? && !error?
      msg.reply stderr if stderr? && !error? 

#テスト実行関数
playTest = (filePath, msg) -> 
    @exec = require('child_process').exec
    command = "mocha #{filePath} --timeout 10000"
    msg.send "TestCase: #{filePath}"
    @exec command, (error, stdout, stderr) ->
      msg.reply error if error?
      msg.reply stdout if stdout?
      msg.reply stderr if stderr?

メッセージを受け取り、テスト名を抽出する

  robot.respond '/.+/', (msg) ->
    @exec = require('child_process').exec
    #渡されたメッセージからテスト名を抽出し、ファイルパスを生成
    requestTxt = msg.match[0];
    testName = requestTxt.replace(/^@.+\s+/, "");
    filePath = "./test/#{testName}.js"

BOTに何かしらメッセージが投げられたら、反応するようにしています。
投げられたメッセージ=実行したいテストファイル名という仕様なので、渡されたメッセージからBOT名を抜いた値をテスト名とし、それをもとにテストファイルのパスを作成しています

ファイル存在チェック

    #ファイルの探索をしてファイルがあればテスト実行し、無ければエラーを返す
    @exec "echo \"var fs = require('fs');fs.statSync('#{filePath}')\" | node", (error, stdout, stderr) ->
      msg.reply "#{testName}:No such Test file" if error?
      playTest filePath, msg if stdout? && !error?
      msg.reply stderr if stderr? && !error? 

ファイルが存在すればテスト実行し、ファイルが無ければエラーメッセージを返します。
少し探してみたのですが、Hubotでファイル存在確認するものが確認できなかったのでnodeのプログラムをコマンド実行してファイルを確認します。

@exec "echo \"var fs = require('fs');fs.statSync('#{filePath}')\" | node", (error, stdout, stderr) ->

大したプログラムでもないのに、ファイル書くのも億劫なのでココはechoで出力したプログラムをnodeが実行するようにしました。

テスト実行

playTest = (filePath, msg) -> 
    @exec = require('child_process').exec
    command = "mocha #{filePath} --timeout 10000"
    msg.send "TestCase: #{filePath}"
    @exec command, (error, stdout, stderr) ->
      msg.reply error if error?
      msg.reply stdout if stdout?
      msg.reply stderr if stderr?

これも、コマンドでテスト実行するようにしています。
そして、テスト結果メッセージを、そのまま返しているような形です。

実行画面

スクリーンショット 2016-08-28 20.25.34.png

selenium_botに対し、clickTestと投げた場合にはテスト実行し、存在しないファイルnoneTestに対してはエラーを返しています。

注意点

パス設定をちゃんと設定する。

NODE_PATHが通っておらず、npmでインストールしたmoduleを読んでくれない事態が発生しました。
下記を実行したところ、上手く行きました。
export NODE_PATH='/usr/local/lib/node_modules'
参考:node.js で Error: Cannot find module 'underscore'

バージョンを新しくする。

node.jsとnpmが古すぎると動きません。ちゃんとバージョンアップしましょう。
参考:Node.jsとnpmをアップデートする方法

挑戦を終えて

リポジトリ
seleniumBOT

coffeescript・Node.jsお初で、一日(8h)でどれだけイケるかなという挑戦も兼ねていたのですが、まぁ思ってたくらいの進捗でした。

次は、もっとテストに関してツッコミたいですね。
今回は起動して動くまでに焦点を合わせたので、node.jsでのテストそのものに関しては手を付ける余裕が無かったです、ハイ。
今まではphpunitが専門だったので、nodeは仕様が違い過ぎて、さすがにキャッチアップ間に合わんでした。
あとは、BOTで投げた時のオプション増やすとかも、やってみたい。

初心者まるだしでツッコミどころが満載だと思うので、編集リクエストやらコメントやら歓迎です。