Intellij IDEAで生成するテストクラスの接尾語を変更する

Intellij IDEAで、Javaなどのクラスから Alt + Enter でテストクラスを生成できる。

ただ、テストフレームワークにSpockを使用する場合、慣例としてテストクラスの接尾語は Spec だが、デフォルトでは接尾語が Test になってしまう。

接尾語の変更ができないかと調べたのでメモ。

環境

Intellij IDEA v2020.3

設定変更方法

Create tests—IntelliJ IDEA

  1. Editor > Code Style > Java を開く
  2. Code Generation タブをクリック
  3. Naming section > suffix を変更

デフォルトでは Test となっているため、 Spec に変更すればいい。

プロジェクトごとの設定のため、JUnitなどとSpockが混在しているプロジェクトではどちらか一方しか設定できない。

振り返り

Eclipse だとテストフレームワークごとに接尾語を変えてくれたので、Intellij IDEA ではやや面倒。

Kotlinのchunkedのように、Javaでサイズ/要素数によるList分割をするにはGuavaかCommons Collectionsを使えばいい

Kotlinの Iterable#chunked が便利だな~と思っていた矢先、JavaでListを複数のリストに分割する機会があった。

検索すると独自の実装方法が上位に出てくるが、たぶんCommons CollectionsGuavaに用意されてるだろうと思ったら、両方にあったのでメモ。

Kotlinのchunked

Iterable または Sequence の関数。引数として数値を取り、その要素数ごとに分割した List を返す。

val list = (0..5).toList() // 0~5までの6要素

// 引数で指定した要素数のサブリストのリストが返る
assert(list.chunked(3) == listOf(listOf(0, 1, 2), listOf(3, 4, 5)))

// 割り切れない場合、末尾のリストの要素数が少なくなる
assert(list.chunked(4) == listOf(listOf(0, 1, 2, 3), listOf(4, 5)))

// 要素数以上の値を指定した場合、先頭のリストにすべての要素が含まれる
assert(list.chunked(6) == listOf(listOf(0, 1, 2, 3, 4, 5)))
assert(list.chunked(7) == listOf(listOf(0, 1, 2, 3, 4, 5)))

第2引数で変換関数を取ることもできるが割愛。

内部的には、Iterable#windowedSequence#windowedの引数 sizestep に第1引数を、 partialWindowstrue を指定している模様。

val list = (0..5).toList()

// windowedのsizeは分割する要素数
// stepは次のリスト生成時の先頭要素の移動数
// partialWindowsはsize未満のリストを保持するか
assert(list.chunked(3) == list.windowed(size = 3, step = 3, partialWindows = true))
assert(list.chunked(5) == list.windowed(size = 5, step = 5, partialWindows = true))
assert(list.chunked(6) == list.windowed(size = 6, step = 6, partialWindows = true))
assert(list.chunked(7) == list.windowed(size = 7, step = 7, partialWindows = true))

Javaでの実装

これをJavaでやりたい場合、Guava v19.0以降、またはCommons Collections v4以降を使用する。

Guava

Guava v19.0で追加された、Lists#partitionで、第1引数のListを第2引数の要素数で分割できる。

分割された内部リストはList#subListによるもののため、第1引数で渡したリストへの変更や、内部リストへの変更がそれぞれに反映されることに注意。

Commons Collections4

Commons Collections v4.0で追加された、ListUtils#partitionを使用可能。

Adapted from http://code.google.com/p/guava-libraries/

とあるように、Guavaの Lists#partition と同じように使える。 List#subList を使っていることなども同じ。

振り返り

Commons Collectionsはv4以上でないと使えないのと、Spring Bootなどのフレームワークを使って実装している場合、依存関係で自然とGuavaが使えたりするので、Guavaのほうが利用のためのハードルは低そう。

独自で実装とかすると、エラー出たときとか面倒なので、極力ライブラリを使いたいものです。

JavaScriptでE2Eテストを記述できる、TestCafeを試してみる

E2Eテストについてちょこちょこ調べていて、ブラウザ操作の自動化でSelenium以外に何かないかなと思っていたら、TestCafeが割と良さそうだったのでメモ。

環境

TestCafe v1.10.0。

インストールにはNode.js v14.15.2、およびYarn v1.22.5を使用。

TestCafeとは

devexpress.github.io

JavaScriptまたはTypeScriptで実装できるE2Eテストツール。

インストールすればすぐに使え、Seleniumのように各ブラウザごとのドライバーなど用意しなくても動かせるのがメリット。

インストール

npmなら npm install -g testcafe 、Yarnなら yarn global add testcafe でグローバルインストールする。

testcafe -v でバージョン表示、 testcafe -b で、利用可能なブラウザ一覧を確認できる。

Redirecting…

FirefoxGoogle ChromeChromiumMicrosoft Edge、おまけでIE11の入ったWindows 10では、インストール時点で以下のように表示される。

$ testcafe -b
Using locally installed version of TestCafe.
firefox
chrome
ie
edge

テスト実行

Redirecting…

コマンドラインから実行する場合、 testcafe [-c 並行実行数] [実行するブラウザ] テスト実装ファイル

ブラウザは firefox,chrome,ie のように、カンマ区切りで複数実行可能。 firefox および chrome は、それぞれ firefox:headless および chrome:headless と記述することで、ヘッドレスモードでも実行できる。

また、 -c 並行実行数 を指定することで、並行実行も可能。

この他にも、後述のFixture名でフィルタリングしたりできる模様。

JavaScriptからの実行

APIを使用して、JavaScriptからも実行できる。

Redirecting…

const createTestCafe = require('testcafe');
const testcafe = await createTestCafe();
const runner = testcafe.createRunner();

await runner
    .src(['tests/fixture1.js', 'tests/fixture2.js'])
    .browsers(['firefox', 'chrome:headless', 'ie'])
    .concurrency(3)
    .run();

テスト実装

fixtureとtest

Redirecting…

テストファイル内に1つ以上のfixtureを、また1つのfixtureにつき1つ以上のtestを記述する。

fixture `MyFixture`;

test('Test1', async t => {
    // テストコードを記述
});

fixture, test、どちらでも、 page で実行する際のURLを指定できる。fixtureにpageを指定すると、そのfixtureに含まれるすべてのtestがそのURLを開いた状態で実行される。testでpageを指定することで、fixtureのURLを上書きできる。

fixture `MyFixture`
    .page `https://google.com`;

test('Test1', async t => {
    // Googleで実行される
});

この他、meta でメタ情報を付与したり、fixtureには beforeEach および afterEach 、testには before および after で前処理/後処理を記述したりできる。

TestController

testの第2引数で渡している関数の引数、 t の実体はTestControllerというクラス。

文字の入力、クリック、エンター押下などはTestControllerを通して行う。

また、 ctx プロパティにKey-Valueで値を設定することで、fixtureとtest間や、testのbeforeとテストコード間などで値の共有が可能。

Selector

HTMLの要素の取得などは、Selectorを使用する。

以下の記述より、SelectorはTestControllerのメソッドに渡されたり、アサート対象になったタイミングで、遅延評価される模様。

The selector value is evaluated each time you :

  • use the selector for an action;
  • assert selector’s properties;
  • call the selector directly in code to get it’s state;

Assert

TestControllerのメソッドとして、Assert用のメソッド expect が用意されている。

expect にactualを渡し、メソッドチェーンで比較用メソッドを実行して期待値を渡す。

expect に渡された値が、Selectorで取得したDOMノードやPromiseの場合、動的ページに対応するために、テストが失敗してもすぐにエラーにはならず、タイムアウトまで複数回実行されるとのこと。Smart Assertion Queryと呼ばれている。

Page Object Pattern

サンプルを見るとほとんど手続き的にテストを書いているが、Page Object Patternでも記述できる模様。

Redirecting…

振り返り

ちょっと試したが、なんといっても複数ブラウザでの実行が、Seleniumに比べると非常に楽。

タイムアウトまで再試行というのは、素のSeleniumを使っているならいざ知らず、Selenideのようなラッパーを使っていれば対応できるので、あまりメリットには感じなかった。

一方、やや不便に感じたのは、非同期処理には async/await を使用しているため、都度記述するのが面倒。これは慣れるしかないか。

セットアップや複数ブラウザ対応が楽というのは、運用開始時にはプラスになるが、運用が始まればあまり意味がなくなるので、既にSeleniumなどのE2Eテスト資産があれば乗り換えるメリットはないが、新規でE2Eテスト環境を構築しようと思っているのであれば十分候補になるかと思った。

Kotlinの@JvmOverloadsをプライマリコンストラクタに書く方法

小ネタ。

Kotlinで、プライマリコンストラクタに @JvmOverloads アノテーションを付ける方法を知らないメンバーがいたのでメモ。

状況

多いのは以下のような data class

data class DataClass(...)

と書かれている場合、 @JvmOverloadsconstructor にしか付与できないため、このままでは記述できない。

対応

class DataClass(...)class DataClass constructor(...) の省略形なので、以下のように constructor を明示し、それにアノテーションを付与してやればいい。

data class DataClass @JvmOverloads constructor(...)

振り返り

3か月くらいKotlinとJavaが混じった環境でコードを書いているが、Javaとの相互運用を考えると、Kotlinオンリーの環境でなければ @JvmOverloads はコンストラクタには必須にしておくほうがよさそう。

GaugeのJava実装を試してみる

前回の続き。

Taikoを使ったJavaScriptによるテスト実装でもろもろ躓いたので、Javaによるテスト実装を試してみる。

環境

Gauge v1.1.5、AdoptOpenJDK v11.0.9.1。

Selenium WebDriverはChocolateyでインストールしたChrome Driverを使用。

JDKのバージョンについて

環境にも書いたが、公式の記述によると、JDK11以上が必要とのこと。

今回はChocolatey の cinst adoptopenjdk11 でインストールした、AdoptOpenJDKを使用。

プロジェクトの作成

前回記事参照java_maven_selenium を選択した。

当初はVSCodeでしか実装できないのかと思ったが、Eclipseプロジェクト用の .classpath.project も生成されており、またテスト実行も mvn test で行えるため、プロジェクト生成をVSCodeで行ってしまえば、任意の開発環境で実装可能と思われる。

(公式では紹介されていないとはいえ、GaugeプラグインのあるIntellijはともかく、Eclipseで実装するのは辛そうだが)

pom.xmlの修正

作成直後では、 pom.xml文字コード指定が行われていない。

mvn test でテストの実行ができるが、UTF-8spec ファイル記述し、そこに日本語などが含まれると、MS932で読み込もうとしてエラーになるため、 project.build.sourceEncoding を追加しておく。

<project ...>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

また、デフォルトではアサーションライブラリとしてAssertjが依存性に含まれているため、適宜変更。JUnit4などのテストフレームワークは依存性に含まれない。

Java実装

公式のWrite Gauge specifications#Step implementationsに、テスト実装の方法が記載されている。

WebDriver用のヘルパークラス

java_maven_selenium でプロジェクトを作成した場合、 driver パッケージに Driver および DriverFactory クラスが生成されている。

Driver.webDriver staticフィールドに、 DriverFactory にて、 System.getenv("BROWSER") に応じた WebDriver インスタンスが設定される。

  1. IE ならば InternetExplorerDriver
  2. FIREFOX ならば FirefoxDriver
  3. それ以外(未指定含む)は ChromeDriver
    • ChromeDriver の場合、 System.getenv("HEADLESS")Y または y ならばヘッドレスモードで実行

異なるWebDriverを利用する場合、DriverFactoryを変更すればいい。

実行フック

JUnit4などと同様、任意の public void メソッドにアノテーションを付与することで、ライフサイクルごとに前処理/後処理が可能。「Test execution hooks」と呼ばれている。

ライフサイクル 前処理 後処理
スイート @BeforeSuite @AfterSuite
スペック @BeforeSpec @AfterSpec
シナリオ @BeforeScenario @AfterScenario
ステップ @BeforeStep @AfterStep

例えば、先の driver.Driver でのWebDriver生成処理は @BeforeSuite で、 WebDriver#quit() の実行は @AfterSuite の付いたメソッドで実行されている。

これらのアノテーションが付与されたメソッドでは、引数として ExecutionContext を指定しておくことで、実行時のコンテキストを取得できる模様。

また、 スイート以外のアノテーションでは、 tags パラメーターを指定することで、特定のタグが付与されている場合のみ実行といったフィルタリングが可能。

デフォルトでは tags に指定したタグのAND条件だが、tagAggregation = Operator.OR を指定しておくことで、OR条件に変更可能。

データの保存

ライフサイクルに応じたデータの保存用に、いくつかのデータストアクラスが用意されている。各ライフサイクルが終了すると、設定されているデータが破棄される。

ライフサイクル データストア
スイート SuiteStore
スペック SpecDataStore
シナリオ ScenarioDataStore

それぞれstaticメソッドとして put(Object key, Object value) , get(Object key) , remove(Object key) などが用意されており、ほぼ Map<Object, Object> として使える。

(というか、中身は ThreadLocal<ConcurrentHashMap<Object, Object>> )

ステップとメソッドの紐づけ

com.thoughtworks.gauge.Step アノテーションに、 .spec で記述したステップの文字列を記述する。

TaikoによるJavaScript開発時と同様、VSCode上でテスト実装のない .spec のステップや、パラメータを使用しているステップと紐づけたメソッドに引数がない/多い場合など、きちんとエラーにしてくれる。

レポートにスクリーンショットを追加

テスト失敗時には、自動的にスクリーンショットが取られ、レポートに出力される。

任意のタイミングでスクリーンショットを取り、レポートに出力したい場合、 com.thoughtworks.gauge.Gauge#captureScreenshot() を実行すると、そのメソッドに対応するステップに、スクリーンショットが追加される。

試しにスクリーンショットを取ってみたが、デフォルトではブラウザだけでなく、デスクトップ画面全体が映っていた。WebDriverのウィンドウサイズを全画面化するなど、ちょっと工夫がいるかもしれない。

レポートにカスタムメッセージを追加

com.thoughtworks.gauge.Gauge#.writeMessage(String format, String... args) を呼び出すと、そのメソッドに対応するステップに、メッセージが追加される。

文字列は String#format(String format, Object... args) でフォーマットされるので、 %sプレースホルダとして利用可能。

実装例

前回のリベンジ。

spec/search.spec に保存していたMarkdownを、以下のように変更。

# 検索エンジンのタイトル確認

Tags: example, search

   |url                    |title |
   |-----------------------|------|
   |https://www.google.com/|Google|
   |https://www.bing.com/  |Bing  |
   |https://yahoo.com/     |Yahoo |

## 検索エンジンを開いて、タイトルを確認する

* URL <url> を開く
* タイトルが <title> となることを確認

続いて、以下のクラスを src/test/java/SearchSpec.java に保存。

import com.thoughtworks.gauge.Gauge;
import com.thoughtworks.gauge.Step;
import driver.Driver;

import static org.assertj.core.api.Assertions.assertThat;

public class SearchSpec {

    @Step("URL <url> を開く")
    public void openSearchEngine(String url) {
        Driver.webDriver.get(url);
        Gauge.captureScreenshot();
    }

    @Step("タイトルが <title> となることを確認")
    public void checkTitle(String expected) {
        String actual = Driver.webDriver.getTitle();
        Gauge.writeMessage("search engine title: %s", actual);
        assertThat(actual).isEqualTo(expected);
    }
}

実行してみると上手くいった。また、 .spec.java のファイル名が別々でも問題なく動いたり、 specs ディレクトリにサブディレクトリを作ってそこに search.spec を移動したり、 SearchSpec.java を適当なパッケージ配下に移動しても問題なく実行できた。

Taikoで試したときの、複数の実装ファイルがあるとエラーになるのは何だったんだ...

振り返り

JUnitこそ使っていないものの、それに寄せて仕様が決められている印象で、特に詰まることなく実装出来た。

src/main 配下にSelenideなどでPage Object Patternに乗っ取ったクラスを記述し、テスト実行はGaugeで、とかできると捗る気がする。

JavaScriptで毎回メソッド名を忘れる、insertAdjacentHTMLとinsertAdjacentElementについて

JavaScriptで、「文字列をElementにHTMLとして追加できて、 innerHTML じゃなくて、第1引数で追加位置を指定できるメソッド、名前なんだっけ?」と毎回なるのでメモ。

insertAdjacentHTML

developer.mozilla.org

モダンブラウザすべてで利用可能。IE4から対応とあるが、もともとはIEの独自実装だった模様。

第1引数の position で、挿入位置を変えられる。文字列なこと、すべて小文字なことに注意。

  • beforebegin: 要素の前
  • afterbegin: 要素の子要素の先頭
  • beforeend: 要素の子要素の末尾
  • afterend: 要素の後

文字列は before|afterbegin|end の組み合わせからなるが、追加位置との対応がわかりにくい。英語力がないからか

insertAdjacentElement

HTML文字列ではなく、Elementを第2引数として指定する、 insertAdjacentElement もある。

developer.mozilla.org

こちらも、モダンブラウザすべてで利用可能。

マイナーなのか、2020/11/28現在で日本語訳されていない。それぞれ、Elementの親インターフェースである、Nodeの insertBeforeappendChild が使われることが多いからかな?

第1引数の position は、 insertAdjacentHTML と同様。子要素への追加は Node.appendChild でいいが、他のパターンは Node.insertBefore を使って頑張るよりもシンプルになると思う。

// 従来の記述方法の例
const targetElement = ...;
const insertElement = ...;

// targetElement.insertAdjacentElement('beforebegin', insertElement); 相当
targetElement.parentNode.insertBefore(insertElement, targetElement);

// targetElement.insertAdjacentElement('afterbegin', insertElement); 相当
targetElement.insertBefore(insertElement, targetElement.firstChild);

// targetElement.insertAdjacentElement('beforeend', insertElement); 相当
targetElement.appendChild(insertElement);

// targetElement.insertAdjacentElement('afterend', insertElement); 相当
targetElement.parentNode.insertBefore(insertElement, targetElement.nextSibling);

備考

insertAdjacentHTML のMDNには、

余分なシリアル化のステップを回避できる分、 innerHTML への代入による直接的な操作よりもはるかに高速な動作となります。

とあるが、以下のページによると、2015年末時点で、それほど大きな差はないみたい。

ginpen.com

innerHTML への代入を使える時は、素直にそちらを使っておいたほうが楽だと思う。

Markdownでテスト仕様書を書けるGaugeを試してみる

E2EテストやATDDについて調べていたら、 Markdown でテスト仕様書を書ける Gauge を知り、ちょっと試してみたのでメモ。

環境

Gauge v1.1.5。テストは Node.js v14.15.0 で記述。

Gauge とは

インテグレーションテスト用の仕様 (Specification) を Markdown で記述し、それに紐づけたテストを実行して結果などを管理するフレームワーク

テスト仕様書を Markdown で記述することで、読み取りが容易となり、再利用性を高められ、また実装を切り分けられる。

テストの実装は、開発元が同じ TaikoSelenium 、またツールを使わずスクレイピングしたりと任意。言語も複数選択可能。

インストール

公式のインストールページを参照。

Windows の場合、Chocolatey でもインストールできるが、バージョンが古いため、公式の手順でインストールを推奨。

2020/11/15 時点で、Chocolatey でインストールできる Gauge は v1.1.1 だが、リリース済みバージョンは v1.1.5。v1.1.1 では、 VSCode からプロジェクトを作成しようとするとエラーが発生する。 ( gauge template が実行されるが、 v1.1.1 時点で template コマンドが未実装)

エディタやIDEとの連携用のプラグインがあるが、公式のインストールページでは、Visual Studio Code しか選択できない。 Intellij IDEA 用のプラグインはあるが、Eclipse 用のプラグインサードパーティ製のものしかない模様。

使い方

前述のインストールページで指定した OS, Language, IDE/Editor で、それ以降の説明が変わる模様。

プロジェクトの作成

https://docs.gauge.org/getting_started/create-test-project.html

VSCode からテスト用のプロジェクトを作成。

コマンドパレットに create project を入力し、 Gauge: Create a new Gauge Project を選択。

コマンド gauge template --list --machine-readable を実行し、言語と説明、テンプレートの ZIP ファイルの URL を JSON で取得していた。

v1.1.5 の時点で、言語およびプロジェクト管理ツールや Selenium との組み合わせで 12 種類。

今回は js を選択。

続いて展開先のディレクトリ選択、最後にプロジェクト名の入力となる。

「展開先ディレクトリ/プロジェクト名」にテンプレート ZIP ファイルが展開され、VSCode の新しいウィンドウで開かれる。

js プロジェクトの場合、ウィンドウが開くまでに npm install が実行されるため、そのまま実行が可能。

Specification の実行

https://docs.gauge.org/getting_started/running-a-specification.html

specs/example.spec を開くと、Markdown 形式のファイルとなっており、最上部に Run Spec | Debug Spec が表示されている。

Run Spec をクリックすると、 npm test が実行され、あらかじめ用意されている spec の実行が可能。

テスト結果の確認

https://docs.gauge.org/getting_started/view-a-report.html

reports/html-report/index.html に、テストレポートが出力される。

Specification の記述

https://docs.gauge.org/writing-specifications.html

Markdown でテスト仕様書を記述できる。

ファイル拡張子は .spec が仕様、 .cpt がコンセプトとなり、 specs/ ディレクトリ配下に保存する。

保存先ディレクトリは env/default/default.properties で変更可能。詳しくはこちら

見出しとシナリオ

h1 タグで仕様の見出しを、h2 タグでシナリオ名を記述。シナリオ配下に、ワークフローを記述していく。

データテーブル

見出しと最初のシナリオの間に、テーブルを記述すると、データテーブルとして扱える。

後述のステップで <テーブルヘッダ名> を記述すると、そのヘッダ名の列の値を動的パラメータとして扱える。

また、シナリオ単位でテーブルを記述してパラメーター化テストを行うこともできるが、実験的機能の模様。

ステップ

順序なしリストをシナリオ配下に記述すると、それぞれがステップとなる。ただ、VSCode 上では * しかステップとして判断されず、 -|+ ではエラーとなる模様。

ステップに " 2 つ、または <> で囲んだ文字列を記述すると、実装コードに引数として渡される。

このため、 " , < , > を単純なテキストとしては記述できない。

" 2 つで囲まれた文字列は静的パラメータとなり、そのまま実装コードに渡される。

<> で前述のデータテーブルのヘッダ名を囲むと動的パラメータとなり、データテーブルから値を取得して実装コードに渡される。

タグ

見出しやシナリオには、 Tags: タグ名[, タグ名] でタグ付けが可能。

記述例では、見出しには Tags: search, admin としてそのテストの分類や対象を、シナリオには成功を期待するテストに Tags: successful がつけられていた。

見出しに付けられたタグは仕様自体のタグとなり、その仕様に含まれるシナリオ全てにも付与される。

コンテキストステップ

見出しと最初のシナリオの間に、ステップを記述すると、コンテキストステップとなる。

各シナリオの実行前にコンテキストステップが実行される。

ティアーダウンステップ

最後のシナリオの後にアンダースコア 3 つ、 ___ で区切り、その後に記述したステップはティアーダウンステップとなる。

各シナリオの実行前にティアーダウンステップが実行される。

コメント

単純なテキストなど、前述の記述以外はすべてコメントとなる。

コンセプト

再利用可能な記述を拡張子 .cpt のファイルに記述可能。

h1 タグでコンセプトヘッダを記述する、そこに <パラメータ名> を含めることが可能。

その直下に順序なしリストでコンセプトステップを記述することで、仕様からコンセプトヘッダを呼び出すことが可能となる。

Taiko でのテストコード実装

Taiko は REPL (Read-Eval-Print Loop) で対話形式に実行可能。ブラウザには Google Chrome が使われる。

yarn global add taiko でインストールし、 taikoインタラクティブレコーダーを実行。

.apiAPI一覧を表示。

コマンドを実行後、 .code [ファイルパス] で実行コマンドを出力 (ファイルパス未指定ではコンソール出力)。

また、 .step で Gauge のステップとして実行可能なコードを出力できる。

.exit で終了。

ツールとしては、スマートセレクター動的コンテンツのロード待ちinterceptによるスタブ化・モック化などの特徴がある。

コマンドプロンプトで実行した場合、タブでのコード補完が効いたり、なかなか使い勝手はいいが、いかんせん情報が少ないのが難点か。

ステップとの紐づけ

js テンプレートの場合、 step('ステップに記述したテキスト', async <function>); を記述すると、ステップから実行できる。

VSCode上で、Specification のステップに対応するテストがない場合はエラーとなったり、テストの step が何か所から実行されるかが分かるようになっている。

パラメータを使用している場合、該当部分を <> で囲み、関数の引数にできる。

実装例

以下の Markdownspec/search.spec に保存。

# 検索エンジンを開く

Tags: example, search

検索エンジンを開く

   |url                    |
   |-----------------------|
   |https://www.google.com/|
   |https://www.bing.com/  |
   |https://yahoo.com/     |

## 検索エンジンを開く

本当は、タイトルの確認くらいはしたかったが、Taikoでタイトルを取得する方法がわからなかったため、ページを開くだけにする

* URL <url> を開く

続いて、 tests/search.js にテストを保存して実行...したら、ブラウザ起動に失敗するようになった。

ファイル名にルールがあるのか、1ファイルしか書けないのか、原因がわからなかったため、デフォルトで用意されている tests/step_implementation.js に以下を追記。

step('URL <url> を開く', async (url) => {
  await goto(url);
});

この状態で、 gauge run specsnpm test を実行すると、テストが実行された。

振り返り

Gauge 自体は非常に使いやすい印象。開発前のユースケースの段階で、自然言語でテスト仕様を記述できる。

一方、 Taiko は情報が少なく、公式のドキュメントを読むしかない状態で、使いこなせれば高機能だと思うが、簡単なテストを書きたいレベルでは、やや扱いにくかった。複数ファイルを tests/ に配置してエラーになったのも、書き方が悪いのか設定で回避できるのか、はたまた仕様かの判断がつけられなかったが、仮に tests/step_implementation.js しか書けないのであれば、ちょっとテストファイルが肥大化しそう。(「テストランナーとの統合」を見ると、ファイル固定っぽい気がする)

既存のテストコードとしては、Selenium を使った PythonJavaのコードが多いので、他言語でのテストプロジェクト作成を試してみたい。

Selenide のような Page Object Pattern との相性は良さそうな気がする。