Help us understand the problem. What is going on with this article?

TestCafeの導入からお問い合わせフォームのSampleまで

More than 1 year has passed since last update.

TestCafeとは

ブラウザテストを自動化するjavascriptのフレームワークになります。
async/awaitやimport機能を使いながらテストコードを書くことができます。

Seleniumとの違い

「Selenium」はjavascriptで書くブラウザテストで有名なフレームワークですが「TestCafe」との大きな違いがあります。

  • TestCafeでは各ブラウザのWebdriverを設定する必要がない
  • Node.jsをインストールしてない環境でもTestCafeでテスト結果を見ることができる。

作業環境構築

TestCafeをインストール

command
$ npm init
$ npm i testcafe -D                       // ローカルにtestcafeをインストール
$ export PATH=$PATH:./node_modules/.bin   // パスを通す
$ testcafe -v                             // versionが表示されればインストール成功

ローカル環境でテスト実行

command
$ npm i http-server -D                                      // ローカルにhttp-serverをインストール
package.json
{
  "name": "testcafe",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "http-server -o"                       // npm startでブラウザ起動
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "http-server": "^0.10.0",
    "testcafe": "^0.18.2"
  }
}
command
$ npm start                                         // http://127.0.0.1:8080が起動

TestCafeのテンプレート

javascript

test.js
// import 文
// 変数・定数等の宣言

fixture('テスト内容の分類やページのタイトル等')
  .page('テストするページのURL');

test('テスト項目名その1', async t => {
  // テスト記入
});

test('テスト項目名その2', async t => {
  // テスト記入
});

test('テスト項目名その3', async t => {
  // テスト記入
});

テスト実行

command
$ testcafe chrome,safari ./test.js

お問い合わせフォームのSample

  • 入力項目「お名前」 ※必須項目
  • 送信ボタンを押下したとき「お名前」が入力されているかチェック
  • 入力された場合、送信する旨をダイアログで表示してthanks.htmlに遷移
  • 入力されない場合、エラーメッセージを表示
  • 戻るボタンを押下したとき「TOPページ」に戻る

HTML

contact.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width">
  <title>TestCafe お問い合わせフォーム</title>
  <style>
    .errorMessage {
      display: none;
    }
    .button {
      display: flex;
    }
  </style>
</head>
<body>
  <form>
    <div class="errorMessage"></div>
    <table>
      <tr>
        <th>お名前 <span></span></th>
        <td><input type="text" name="name" class="name" required /></td>
      </tr>
    </table>
    <div class="button">
      <div><input type="button" value="戻る" class="back" onclick="location.href='/demo/'" /></div>
      <div><input type="button" name="submit" value="送信" class="submit" /></div>
    </div>
  </form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
  $(function() {
    formAction.init();
  });
  /*
  名前入力が空白だったらエラーメッセージを表示
  名前入力の値をSessionStorageのnameにsetして、thanks.htmlでgetする
   */
  var formAction = {
    init: function() {
      var self = this;
      self.nameSelector = $('.name');
      self.errorMessageSelector = $('.errorMessage');
      self.submitSelector = $('.submit');
      self.errorMessageNone = self.errorMessageSelector.hide();
      self.submitAction();
    },
    submitAction: function() {
      var self = this;
      self.submitSelector.on('click', function() {
        if (self.nameSelector.val() === '') {
          self.errorMessageAction(true);
          return false;
        }
        self.errorMessageAction(false);
        self.confirmAction();
      });
    },
    errorMessageAction: function(errorMessage) {
      var self = this;
      if (errorMessage) {
        self.errorMessageSelector.show().text('必須項目にご記入ください');
      } else {
        self.errorMessageNone;
      }
    },
    confirmAction: function() {
      var self = this;
      if (confirm('この内容で送信します。')) {
        self.submitSelector.prop('disabled', true);
        sessionStorage.setItem('name', self.nameSelector.val());
        setTimeout(function() {
          document.location.href = 'thanks.html';
        }, 1000);
      } else {
        return false;
      }
    }
  }
</script>
</body>
</html>
thanks.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width">
  <title>TestCafe 完了画面</title>
</head>
<body>
  <p class="thanksMessage">
    <span class="name"></span>様、お問い合わせありがとうございます。
  </p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
  $(function() {
    thanksAction.init();
  });
  /*
  名前の値をSessionStorageから取得する
   */
  var thanksAction = {
    init: function() {
      var self = this;
      self.nameSelector = $('.name');
      self.nameGet = sessionStorage.getItem('name');
      self
      self.thanksDisplay();
    },
    thanksDisplay: function() {
      var self = this;
      self.nameSelector.text(self.nameGet);
    }
  }
</script>
</body>
</html>
index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width">
  <title>TestCafe</title>
</head>
<body>
  <p>TOPページ</p>
</body>
</html>

テストコード

contactTest.js
import Page from  './pageModel';
import { ClientFunction } from 'testcafe'; // 現在のページのURLを確認

const page = new Page();
const getWindowLocation = ClientFunction(() => window.location);

fixture('お問い合わせフォーム')
  .page('http://127.0.0.1:8080/demo/contact.html'); // 実行するページ

test('必須項目を入力して確認後、thanksページに遷移', async t => {
  await t
    // テスト実行速度 1が最高速 0.01が最低速
    .setTestSpeed(page.setTestSpeed)
     // ダイアログの操作
    .setNativeDialogHandler(() => true)
    // アクション
    .typeText(page.nameSelector, '佐藤一郎')
    .click(page.submitSelector);
  // アサーション(求める結果)
  await t.expect(page.thanksMessage.innerText).eql('佐藤一郎様、お問い合わせありがとうございます。');
});

test('必須項目に入力されていないとき、errorMessageを表示', async t => {
  await t
    .setTestSpeed(page.setTestSpeed)
    .click(page.submitSelector);
  await t.expect(page.errorMessage.innerText).eql('必須項目にご記入ください');
});

test('戻るを押下したときにtopページに戻る', async t => {
  await t
    .setTestSpeed(page.setTestSpeed)
    .click(page.backSelector);
    const location = await getWindowLocation(); // ページ遷移してから現在のURLを取得
  await t.expect(location.pathname).eql('/demo/');
});
pageModel.js
import { Selector } from 'testcafe';

/*
  Page Object
 */
export default class Page {
  constructor () {
    this.nameSelector = Selector('.name');
    this.submitSelector = Selector('.submit');
    this.thanksMessage = Selector('.thanksMessage');
    this.errorMessage = Selector('.errorMessage');
    this.backSelector = Selector('.back');
    this.setTestSpeed = 0.5;
  }
}

テスト実行

command
$ testcafe chrome ./contactTest.js

Running tests in:
 - Chrome 61.0.3163 / Mac OS X 10.13.1

 お問い合わせフォーム
 ✓ 必須項目を入力して確認後、thanksページに遷移
 ✓ 必須項目に入力されていないとき、errorMessageを表示
 ✓ 戻るを押下したときにtopページに戻る


 3 passed (8s)

 参考サイト

macotok
Reactでviewを作って、Firebaseでサーバーを作ってるところ
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした