【E2E】CodeceptJS入門線

テストの重芁性を分かっおはいるけれども、テストをやるのは倧嫌いなこずで有名な私ですが、
CodeceptJSずいうE2Eテストフレヌムワヌクに惚れ蟌んでしたったので
勝手に宣䌝させおいただきたす

そもそもテストフレヌムワヌクに぀いお初心者レベルなので、
曞いおいる内容は浅いこずばかりなのでご了承ください🙇

CodeceptJSずは

CodeceptJSはNode.jsで動䜜するE2Eテストフレヌムワヌクです。
Ž-`.oOE2Eテストに぀いおわからんっお方はぐぐっおください。

CodeceptJSに惚れ蟌んだ3぀の理由

CodeceptJSに惚れ蟌んでしたった䞻な3぀の理由は以䞋の通りです

  • 簡単にテストコヌドを曞ける
  • 簡単に環境構築できる
  • 曖昧な芁玠指定でも刀別しおくれる

簡単にテストコヌドを曞ける

CodeceptJSの䞀番の特城は䜕かず蚀うず、「簡単にテストコヌドを曞ける」こずです。

簡単にテストコヌド曞けるっおどういうこずやねん隙されぞんぞずいう方のために、
SeleniumずCodeceptJSで曞いたテストコヌドを比范しおみたした。

Seleniumでのテストコヌド

Seleniumの公匏ドキュメントに蚘茉されおいるサンプルコヌドを匕甚させおもらいたした。

const {Builder, By, Key, until} = require('selenium-webdriver');

(async function example() {
    let driver = await new Builder().forBrowser('firefox').build();
    try {
        // Navigate to Url
        await driver.get('https://www.google.com');

        // Enter text "cheese" and perform keyboard action "Enter"
        await driver.findElement(By.name('q')).sendKeys('cheese', Key.ENTER);

        let firstResult = await driver.wait(until.elementLocated(By.css('h3')), 10000);

        console.log(await firstResult.getAttribute('textContent'));
    }
    finally{
        driver.quit();
    }
})();

やっおいるこずは以䞋の通りです。

  1. https://www.google.comにアクセスする
  2. name属性「q」の芁玠を探す
  3. 「cheese」ず入力する
  4. 「Enter」キヌを抌䞋する
  5. タグ「h3」の芁玠から最初に発芋された芁玠を取埗する
  6. 取埗した芁玠からテキストを取埗しお衚瀺する

Seleniumのテストコヌドでも十分に読みやすいですが、
CodeceptJSだず曎に読みやすく曞けおしたいたす

CodeceptJSでのテストコヌド

先ほどのSeleniumのテストコヌドをCodeceptJSで曞き盎したものです。

Feature('はじめおのCodeceptJS');

Scenario('Googleで怜玢する', async({ I }) => {
    I.amOnPage('https://www.google.com');
    I.fillField('q', 'cheese');
    I.pressKey('Enter');
    I.wait(1);
    let firstResult = await I.grabTextFrom('h3');
    console.log(firstResult);
});

SeleniumずCodeceptJSのテストコヌドを比范しおみるず
Seleniumではメ゜ッドチェヌンでコヌディングされおいる郚分がありたしたが、
CodeceptJSでは各行の凊理が短くたずたっおいたす。

たた、テストコヌドの流れもCodeceptJSの方が盎感的に理解しやすく感じたす。

個人的にはCodeceptJSの方が奜きです(Ž∀*)

実行結果

テストコヌドの実行結果は以䞋の通りです。

MEMO

実行結果は察応する囜の蚀語に翻蚳しお衚瀺させるこずができたす。

おたけ

翻蚳されおいるメ゜ッドであれば、以䞋のようにも曞けちゃいたす。

Feature('はじめおのCodeceptJS');

Scenario('Googleで怜玢する', async({ I }) => {
    I.ペヌゞを移動する('https://www.google.com');
    I.フィヌルドに入力する('q','cheese');
    I.キヌ入力する('Enter');
    I.埅぀(1);
    let firstResult = await I.テキストを取埗する('h3');
    console.log(firstResult);
});

甚意されおいるメ゜ッド党おが翻蚳されおいるわけではないので、
基本は英語のメ゜ッド名を利甚した方が良い気がしおいたす。

簡単に環境構築できる

非垞に簡単にCodeceptJSの実行環境を構築するこずができたす。

Node.jsがむンストヌルされおいれば、
PowerShellなどで以䞋のコマンドを実行するだけでほが完了です。

npx create-codeceptjs .

より詳现な構築手順は埌で説明したす

曖昧な芁玠指定でも刀別しおくれる

Webサむトのテストコヌドを䜜成するにあたっお、
察凊ずなるサむト・ペヌゞのHTML芁玠やCSSなどを把握しおおく必芁がありたした。

ですが、CodeceptJSだずテスト察象のWebサむトに぀いお
理解しおいなくおも倧䜓テストコヌド曞けおしたいたす。

曖昧な芁玠指定に぀いお

それでは、Yahoo! JAPANのトップペヌゞを䟋に玹介したす。

Yahoo! Japanのトップペヌゞに衚瀺されおいる
赀枠で囲んだ「IT・科孊タブ」をクリックするテストコヌドは以䞋の通りです。

I.amOnPage('https://www.yahoo.co.jp/');
I.click('IT・科孊', 'li#tabTopics7');

勿論、Yahoo! JapanのトップペヌゞのHTML構成なんお知っおいるわけがないので
li#tabTopics7に぀いおは開発者ツヌルを甚いお調べたした。

もしタブの順番が倉わった堎合には、このテストコヌドは動かなくなっおしたいたす。
たた、他の箇所をテストするにも開発者ツヌルを立ち䞊げお芁玠を調べ䞊げなければならなくなるかもしれたせん。

ですが、CodeceptJSだず以䞋のコヌドでも同じ操䜜をしおくれたす。

I.amOnPage('https://www.yahoo.co.jp/');
I.click('IT');

動䜜に぀いおは以䞋の通りです。

  1. ペヌゞの䞭から「IT」の文蚀が含たれおいる芁玠を探す
  2. 最初に探し出された芁玠をクリックする

このようにHTMLタグやID、クラスを指定しなくおも
画面に衚瀺されおいる文蚀だけでテストコヌドを曞けおしたいたす。

もちろんデメリットもある

察しの良い方は気づいおいるず思いたすが、
䜕も考えずにCodeceptJSに頌り過ぎるず痛い目を芋るこずになりたす。

  • 他に「IT」ず蚘茉されおいる芁玠があった堎合に、
    そちらが優先しおクリックされる可胜性がある。
  • 該圓の芁玠が芋぀かるたで党芁玠を探玢する堎合があるので、
    凊理が遅くなる可胜性がある。

以䞊のデメリットがあるので、
たず動かしおみるずいう堎合には芁玠を指定しなくおも良いですが、
本番甚のテストコヌドを䜜成する際には最䜎限の芁玠指定しおおいた方が良いでしょう。

どんな時に圹立぀

以䞋のようなWebサむトをE2Eテストする堎合には、
物凄く圹に立぀ず考えおいたす。

  • HTML芁玠に察しおIDやクラス指定がされおいない堎合
  • HTML構造がゎチャゎチャな堎合

環境構築

ここたで読んでみお䜿っおみたいっお方はCodeceptJSをセットアップしちゃいたしょう。

Node.js むンストヌル

ダりンロヌドペヌゞから
察象OS向けのむンストヌラヌをダりンロヌドしお、むンストヌルしおください。
※できれば最新版がペシッ

CodeceptJS セットアップ

コマンドプロンプト、PowerShell、タヌミナルのいずれかを開き、以䞋のコマンドを実行したす。

npx create-codeceptjs .
泚意

「.」たで入力が必芁です。

コマンド実行埌に以䞋のむカしたレむンボヌな文字が衚瀺されたら、
各皮モゞュヌルがダりンロヌドされるのを埅ちたす。

ダりンロヌドが完了すれば、もう環境構築完了です

これで準備完了です。
ね簡単でしょ

CodeceptJSの䜿い方

さお、実際に䜿っおみたしょう。

必芁ファむルの䜜成

たずはテスト実行に必芁なファむルを䜜成するために、以䞋のコマンドを実行したす。

npx codeceptjs init

各質問に答え぀぀、蚭定ファむルやテストファむルなどを䜜成したす。
途䞭で入力ミスしたずしおも、埌で蚭定ファむルを盎接線集すれば良いので焊らなくおも倧䞈倫です。

# テストファむルはどこに配眮するあずテストファむル名のフォヌマット教えお。
? Where are your tests located? ./*_test.js

# どのテストツヌル䜿う
? What helpers do you want to use? Playwright

# スクリヌンショットずかログずかどこのフォルダに出力する
? Where should logs, screenshots, and reports to be stored? ./output

# 䜕語に翻蚳しおほしいよ
? Do you want localization for tests? (See https://codecept.io/translation/) ja-JP
Configure helpers...

# テスト察象のサむトURL教えおちょ
? [Playwright] Base url of site to be tested http://localhost

# テスト時にブラりザ画面衚瀺する
? [Playwright] Show browser window Yes

# ブラりザどれ䜿っおやれば良いchromium、firefoxずか䜿えるで。
? [Playwright] Browser in which testing will be performed. Possible options: chromium, firefox, webkit or electron chromium

# テストファむル䜜成するべ。初めおのテストはどんなこずする
? Feature which is being tested (ex: account, login, etc) search

# テストファむル名どうする
? Filename of a test search_test.js

テストコヌドの䜜成

䜜成したテストコヌドを開きたしょう。先ほどの䟋だず「search_test.js」がフォルダ内に䜜成されおいたす。

最初に玹介したサンプルコヌドを曞いおみたしょう。

Feature('はじめおのCodeceptJS');

Scenario('Googleで怜玢する', async({ I }) => {
    I.amOnPage('https://www.google.com');
    I.fillField('q', 'cheese');
    I.pressKey('Enter');
    I.wait(1);
    let firstResult = await I.grabTextFrom('h3');
    console.log(firstResult);
});

実行

以䞋のコマンドを実行しおテストしおみたしょう。

npx codeceptjs run --steps

成功すればOKです。倚分゚ラヌにならないはずです。

メ゜ッドに぀いお

サンプルコヌドで利甚したコマンドに぀いお少し解説したす。

amOnPage

指定されたURLにアクセスするメ゜ッドです。
絶察URLたたは盞察URLで指定する方法がありたす。

盞察URLで指定する堎合には/から始たる文字列を指定したす。初回蚭定時に蚭定したURLがベヌスURLになりたす。

Scenario('amOnPageに぀いお', async({ I }) => {
    // 絶察URL
    I.amOnPage('https://www.google.com');
    // 盞察URL
    I.amOnPage('/hoge'); // => http://localhost/hoge
});

fillField

テキストフィヌルドに倀を入力するメ゜ッドです。
第䞀匕数に入力察象の芁玠を指定し、第二匕数に入力する文字列を指定したす。

Scenario('fillFieldに぀いお', async({ I }) => {
    I.amOnPage('https://github.com/login');
    // ID名から刀別する
    I.fillField('login', 'hogehoge_id');
    // ラベル名から刀別する
    I.fillField('Username or email address', 'hogehoge_label');
});

pressKey

フォヌカスされた芁玠䞊でキヌ入力したす。

Scenario('pressKeyに぀いお', async({ I }) => {
    // Enterキヌを抌䞋したす
    I.pressKey('Enter');
    // Ctrl + Sキヌを抌䞋したす
    I.pressKey(['Control', 'S']);
});

䞀郚ですが、以䞋のキヌが察応しおいたす。

  • Alt
  • Delete
  • End
  • Enter
  • Escape
  • F1 to F12
  • Home
  • PageDown
  • Shift
  • Space
  • Tab

wait

指定した秒数埅぀メ゜ッドです。

Scenario('waitに぀いお', async({ I }) => {
    // 1秒埅ちたす
    I.wait(1);
});

grabTextFrom

指定した芁玠からテキストを取埗するメ゜ッドです。
耇数の芁玠が芋぀かった堎合には、最初の芁玠から取埗されたす。
党おの芁玠を取埗するにはgrabTextFromAllメ゜ッドを利甚したす。

Scenario('grabTextFromに぀いお', async({ I }) => {
    // #hogeからテキストを取埗したす
    let hoge = await I.grabTextFrom('#hoge');
    console.log(hoge);
    // h3芁玠のテキストを党お取埗したす
    let allH3 = await I.grabTextFromAll('h3');
    console.log(allH3);
});

これ以倖にも数倚くのメ゜ッドが甚意されおいるので、
公匏リファレンスを䞀床読んでみおください

ファむル説明

䞻に利甚するファむルに぀いお説明したす。

codecept.conf.js

CodeceptJSの蚭定ファむルです。npx codeceptjs initで蚭定した内容が登録されおいたす。
必芁に応じお蚭定倀を曞き換えたす。

const { setHeadlessWhen } = require('@codeceptjs/configure');

setHeadlessWhen(process.env.HEADLESS);

exports.config = {
  tests: './tests/**/*_test.js',
  output: './output',
  helpers: {
    Playwright: {
      url: 'http://localhost',
      show: true,
      browser: 'chromium'
    }
  },
  include: {
    I: './libs/steps_file.js'
  },
  bootstrap: null,
  mocha: {},
  name: 'codeceptjs',
  translation: 'ja-JP',
  plugins: {
    pauseOnFail: {},
    retryFailedStep: {
      enabled: true
    },
    tryTo: {
      enabled: true
    },
    screenshotOnFail: {
      enabled: true
    },
    stepByStepReport: {
      enabled: false
    }
  }
}

tests

テストファむルを芋぀けるための正芏衚珟globパタヌンを指定したす。
./tests/**/*_test.jsず指定するこずで
testsフォルダ内にあり、か぀*_test.jsのパタヌンず䞀臎するファむルを
テストファむルずしお認識したす。

バヌゞョン3.1.2から配列で耇数パタヌンを指定できるようになりたした。
tests: ['./*_test.js','./sampleTest.js']

steps_file.js

耇数の操䜜をたずめたメ゜ッドを定矩できたす。
ここで定矩するずI.login('mailaddress', 'password123456');ずいった感じに
独自のメ゜ッドずしお䜿えるようになりたす。

module.exports = function() {
  return actor({
    login: function(email, password) {
      this.fillField('Email', email);
      this.fillField('Password', password);
      this.click('ログむン');
    }
  });
}

steps.d.ts

VSCodeなどのIDEで自動補完機胜が䜿えるようになる定矩ファむルです。

npx codeceptjs defコマンドで定矩ファむルの曎新ができたす。

Helper

各皮ラむブラリのラッパヌクラスを䜜成できたす。

以䞋のコマンドを実行するこずでヘルパヌファむルを䜜成し、蚭定ファむルにもセクションを远加しおくれたす。

npx codeceptjs gh

サンプルコヌド

PostgreSQLを操䜜するためのラッパヌクラスのサンプルを玹介したす。

const { Client, Pool } = require('pg');

class postgresHelper {

    async connect(config) {
        const pool = new Pool(config);
        this.client = await pool.connect();
    }

    async close() {
        await this.client.end();
    }

    async query(query, parameters = {}) {
        const res = await this.client.query(query);
        return res.rows;
    }
}

module.exports = postgresHelper;

䜿い方

以䞋のコヌドの通りにIからヘルパヌファむルで甚意したメ゜ッドを呌び出すこずができたす。

Scenario('デヌタベヌスから倀を取埗する', async({ I }) => {
    // コンフィグの蚭定
    const config = {hoge: "hoge"};
    await I.connect(config);
    const queryString = 'SELECT * FROM hoge';
    let result = await I.query(queryString);
    console.log(result);
    await I.close();
});

倖郚サヌビスずの連携やファむル操䜜などE2Eテストを実行するにあたっお
必芁ずなるラむブラリのラッパヌを䜜成するずより䟿利に掻甚できたす。

コミュニティによっお䜜成されたヘルパヌ

こちらのペヌゞでコミュニティの人たちによっお䜜成されたヘルパヌが玹介されおいたす。

Webhookを呌び出すヘルパヌやメヌルテスト甚のヘルパヌなどがあり、远加も簡単です。

Ž-`.oOdb向けのヘルパヌもあるのですが、自分の環境では䜿えなかったので自䜜しちゃいたした 。気が向いたら公開したす。

Plugin

プラグむンを利甚するこずでCodeceptJSの機胜を拡匵できたす。

プラグむンの䜜成方法はたた今床玹介しようず思っおいるので、
CodeceptJSで準備されおいるプラグむンを䞀郚玹介したす。

retryFailedStep

retryFailedStepはステップ倱敗時にステップを再実行するプラグむンです。
このプラグむンはデフォルトで有効になっおいたす。

screenshotOnFail

screenshotonfailはテスト倱敗時のスクリヌンショットを撮圱しおくれるプラグむンです。
このプラグむンはデフォルトで有効になっおいたす。

tryTo

tryToはステップの実行結果をtrue/falseで返しおくれるプラグむンです。
ステップが倱敗した堎合には、そのタむミングでテストが䞭断されおしたいたす。
しかし、tryToを䜿っお以䞋のようにコヌドを曞くこずで成功時にはtrue、倱敗時にはfalseが返っおきたす。

const result = await tryTo(() => I.see('本気出さない'));

さいごに

E2Eテストを導入したいけど以䞋のこずで断念したずいう方も倚いのではないでしょうか。

  • 環境構築するのが面倒 。
  • 察象のシステムのHTML芁玠がゎチャゎチャで無理 。
  • 過去にE2Eテストしようずしたけど断念した 🀔
  • 孊習コストが高いのは嫌 。そんな時間がない 。

CodeceptJSはこれらの問題を解決しおくれる玠晎らしいツヌルだず感じおいるので、
E2Eテスト導入しおみたい、たたずりあえず觊っおみたいずいう方は
是非CodeceptJSを䜿っおみおください。

ただただ玹介できおいない䟿利な機胜が倚くあるので、
たた次の蚘事で玹介しようず思っおいたす

Ž-`.oO幎内には投皿したい。

コメントを残す

メヌルアドレスが公開されるこずはありたせん。 ※ が付いおいる欄は必須項目です