こんにちは。キャスレーコンサルティング LS(リーディングサービス)部の清水(皓)です。
業務で自動テスト環境を構築する機会があり、Selenium+ImageMagick+C#でブラウザテストを書きました。
私はコーディングするのは好きですが、テストを行うことは苦手です。
しかし、書いたコードはテストしないと、頭の中で繰り返し書いたコードを思い出し、
バグを見つけてしまい、夜も眠れなくなってしまいます。
そこで、品質と生産性、心の安定を求めて他のテストツールにも興味が湧いたのですが、
今回はその中でも色々と便利に使えそうな、WebdriverIOを勉強中のTypeScriptで使ってみました。
TypeScript、WebdriverIO、Seleniumで自動テスト環境を構築し、テストを自動化していきましょう。
自動テスト環境を整備することで、リグレッションテストが効率化され、新規開発に注力できるようになっていきます。
なぜWebdriverIOか
業務では、C#とImageMagickというお告げがあったため、Selenium-Webdriverを使いましたが、
コードが冗長で、書きにくいと感じました。
シンプルに書きたい、手が疲れると思ったところ、
WebdriverIOとNightmareの二つがコードをシンプルに書けそうだと思い、
クロスブラウザ対応していることから、WebdriverIOを選びました。
NightmareはElectronを使っていて面白そう、名前がカッコいいなどGoodなポイントがありました。
こちらは後々、遊んでみようと思っています。
環境構築
環境構築を行っていきますが、私の開発環境はWindows10にVisualStudioCodeとなっておりますので、
その点ご了承ください。
TypeScriptの開発環境構築
以前、TypeScriptをVisualStudio Codeで書くための記事を書きましたので、下記をご参照ください。
Visual Studio CodeではじめるTypeScript入門
プロジェクトフォルダの作成
今回の作業用に、プロジェクトフォルダを作成しましょう。
VisualStudioCodeを開き、ファイル(F)→フォルダを開く(Ctrl+K Ctrl+O)からプロジェクトフォルダを選択できます。
プロジェクトフォルダを新規作成して選択します。
続いて、作成したプロジェクトフォルダに、package.jsonを作成しましょう。
PowerShellやコマンドプロンプトを開き、作成したプロジェクトフォルダに移動したら、以下のコマンドを入力します。
npm init –y
TestWDIO\package.jsonファイルが、作成されました。
npmコマンド入力のために開いた、PowerShellやコマンドプロンプトは、
この後も使用するため、そのままにしておいてください。
WebdriverIOのインストール
WebdriverIOにはnode.jsも必要ですが、TypeScriptの開発環境構築で参照いただいた記事の中で、
インストールしていますので、ここでは割愛します。
npm install webdriverio --save-dev
Seleniumのインストール
今回は、ローカル環境でブラウザを操作させるため、Selenium Standalone Serverをインストールします。
npm install selenium-standalone --save-dev
以前の記事でも、Seleniumの自動テストについて紹介させていただいていますが、
そちらはFirefoxのアドオン、Selenium-IDEを使用しています。
しかし、自動実行テストの意義説明や、テストコードを書かずにブラウザ操作を自動実行させる手順を紹介していますので、
自動実行の利点が知りたい方や、テストコードを書くのは難しいと感じる方は、
下記の記事をご覧いただき、是非自動化に取り組んでみて下さい。
Seleniumを利用しWeb画面を自動実行してみよう【導入編】
Seleniumを利用しWeb画面を自動実行してみよう【応用編】
WebdriverIOの設定
WebdriverIOをインストールしたことで、プロジェクトフォルダに「node-modules」フォルダが作成されています。
以下のコマンドで、WebdriverIOの設定を開始します。
.\node_modules\.bin\wdio config[
英語での対話形式で設定を行っていきますが、特に難しい文章ではなく、
設定内容も選択式なので、サクサク設定できると思います。
おおよそ、以下の内容を設定していくことになります。
- テストの実行環境
「On my local machine」を選択します。
選択肢の中に、テスト実行環境のクラウドサービスがあることから、
このようなサービスを使用する設定も容易に行えることが分かります。
- 使用するテストフレームワーク
Mocha、jasmine、cucumberの中から選べます。好みのフレームワークを、選択してください。
私のおすすめは、シンプルかつ機能が豊富なjasmineです。
また、フレームワークで使用するアダプタや、ライブラリのインストールを聞かれることがあります。
- Specファイルの配置
./test/spec/*.jsと入力します。
- レポーターの種類
ここも好みで選んでいただいて構いません。WebdriverIOの公式サイトで、レポーターの特徴が説明されています。
- テストに使用するサービス
もちろん、Selenium-Standaloneを選びます。
- ログ出力レベル
無難にerrorにしておきます。
- コマンド失敗時のスクリーンショット保存先
ここもそのままEnterか、任意の保存先のパスを入力してください。
- テストサーバのベースURL
http://localhost:8080など、テストしたいアプリケーションやWebサイトのURLを入力します。
========================= WDIO Configuration Helper ========================= ? Where do you want to execute your tests? On my local machine ? Which framework do you want to use? jasmine ? Shall I install the framework adapter for you? Yes ? Where are your test specs located? ./test/specs/*.js ? Which reporter do you want to use? spec - https://github.com/webdriverio/wdio-spec-reporter ? Shall I install the reporter library for you? Yes ? Do you want to add a service to your test setup? selenium-standalone - https://github.com/webdriverio/wdio-selenium- standalone-service ? Shall I install the services for you? Yes ? Level of logging verbosity error ? In which directory should screenshots gets saved if a command fails? ./errorShots/ ? What is the base url? http://localhost:8080
これで、WebdriverIOの設定が完了しました。
VisualStudioCodeのエクスプローラーから、wdio.conf.jsを開いて内容を確認してみましょう。
Capabilitiesのセクションに、インスタンス数と使用するブラウザを設定できます。
デフォルトではFireFoxが設定されていますが、使用しているブラウザに変更しましょう。
capabilities: [{ // maxInstances can get overwritten per capability. So if you have an in-house Selenium // grid with only 5 firefox instances available you can make sure that not more than // 5 instances get started at a time. maxInstances: 5, // browserName: 'firefox' }],
ブラウザをChromeに変更します。
capabilities: [{ // maxInstances can get overwritten per capability. So if you have an in-house Selenium // grid with only 5 firefox instances available you can make sure that not more than // 5 instances get started at a time. maxInstances: 5, // browserName: 'chrome' }],
ブラウザ起動時にヘッドレスモードのオプションを設定したり、複数ブラウザで同時にテストを実行したり、
特定のテスト実行時のみ特定ブラウザで起動したり、といったこともCapabilitiesセクションの設定で行えます。
capabilities: [{ browserName: 'chrome', chromeOptions: { // to run chrome headless the following flags are required // (see https://developers.google.com/web/updates/2017/04/headless-chrome) // args: ['--headless', '--disable-gpu'], } }, { // maxInstances can get overwritten per capability. So if you have an in house Selenium // grid with only 5 firefox instance available you can make sure that not more than // 5 instance gets started at a time. maxInstances: 5, browserName: 'firefox', specs: [ 'test/ffOnly/*' ], "moz:firefoxOptions": { // flag to activate Firefox headless mode (see https://github.com/mozilla/geckodriver/blob/master/README.md#firefox-capabilities for more details about moz:firefoxOptions) // args: ['-headless'] } },{ browserName: 'phantomjs', exclude: [ 'test/spec/alert.js' ] }],
その他のセクションの設定も気になる方は、WebdriverIOのページをご参照ください。
型定義ファイルのインストール
WebdriverIOやjasmineのメソッドを、Typescriptで書くために型定義が必要となります。
npmでWebdriverIOとjasmine(mochaやcucumberをインストールした場合はそちら)の
型定義ファイルも入れてしまいましょう。
npm install --save @types/webdriverio
npm install –save @types/jasmine
型定義が無いと、エディタ上に波線で警告が出てしまいます。
テストコードを書く
ページオブジェクトパターンを使ってテストを書くと、
テスト対象ページの操作を必要な分に限定でき、ページ修正の影響範囲を限定できます。
以下のようなフォルダ構成を作成し、ページオブジェクトパターンでテストコードを書いていきたいと思います。
.\TESTEDIO
├node_modules
├pages …(TypeScriptのページオブジェクトクラス用フォルダ)
├specs …(TypeScriptのテストクラス用フォルダ)
├test
│ ├pages …(トランスパイルしたページオブジェクトクラス用フォルダ)
│ └specs …(トランスパイルしたテストクラス用フォルダ)
├package-lock.json
├package.json
└wdio.conf.js
tsconfig.jsonの作成
TypeScriptをトランスパイルするための設定ファイルを、先に準備しておきましょう。
package.jsonと同じ階層にtsconfig.jsonファイルを新規作成し、以下の通り設定を行います。
{ "compilerOptions": { "target": "es5", "module": "commonjs", "moduleResolution": "node", "outDir": "test/", "types":[ "webdriverio", "jasmine" ] }, "exclude": [ "node_modules" ], "compileOnSave": false }
“types”セクションに、インストールした型定義を指定します。
TypeScriptのテストコード
Googleにアクセスして、弊社を検索し、弊社ホームページにアクセスするテストを書いていきます。
まずは、Googleページのページオブジェクトクラスを作成します。
.\pages\googlePage.ts
// Googleページのクラス class GooglePage { // Googleの検索欄(Google を検索または URL を入力)要素 public get searchTextBox() { return browser.element('#lst-ib') } // Googleページを開く public open(): void { browser.url('https://google.com') } } const googlePage = new GooglePage() export default googlePage
次に、検索結果ページのページオブジェクトクラスを作成します。
.\pages\searchPage.ts
// Google検索結果ページのクラス class SearchPage { // キャスレーのホームページへのリンクをクリック public casleyLinkClick(): void { browser.click('=キャスレーコンサルティング株式会社 | お客様と社会、従業員すべてに共通 ...') } } const searchPage = new SearchPage() export default searchPage
弊社ホームページの、ページオブジェクトクラスも作成します。
.\pages\casleyPage.ts
// キャスレーホームページのクラス class CasleyPage { // ページタイトル取得 public get title() { return browser.getTitle() } } const casleyPage = new CasleyPage() export default casleyPage
最後に、テストクラスを作成します
.\specs\sample.ts
// assertモジュールをロード var assert = require('assert') // Googleページクラスをインポート import GooglePage from '../pages/googlePage' import SearchPage from '../pages/searchPage' import CasleyPage from '../pages/casleyPage' // 30秒まで延ばす jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; describe('search casley', () => { it('ようこそ、キャスレーコンサルティングのホームページへ', () => { GooglePage.open(); GooglePage.searchTextBox.setValue('キャスレーコンサルティング').keys('Enter'); SearchPage.casleyLinkClick(); assert.equal(CasleyPage.title, 'キャスレーコンサルティング株式会社 | お客様と社会、従業員すべてに共通した価値をもたらすビジネスとサービスをITで創り出すこと、それが私たちキャスレーコンサルティングのビジョンです。'); }); });
各ページオブジェクトには、対象ページで行える操作やページに存在する要素のみを実装することで、
テストクラスで想定外の動作を、させないようにすることができます。
テスト実行
それでは、トランスパイルして実行してみましょう。
トランスパイルすると、.\testフォルダ配下にpagesフォルダやspecsフォルダができ、
その下にJavaScriptのページオブジェクトクラスファイルと、テストクラスファイルが生成されます。
PowerShellまたはコマンドプロンプトで、以下のコマンドを実行しましょう。
.\node_modules\.bin\wdio
Chromeが起動し、Googleで弊社を検索、弊社ホームページにアクセスするところまで、自動で実行されたと思います。
テスト結果が、以下の通り表示されます。
------------------------------------------------------------------ [chrome #0-0] Session ID: 618dd586e2b3c4297d92a0e11b7d548e [chrome #0-0] Spec: C:\Users\GlowWhite\Documents\VSCODE_TEST\TestWDIO\test\specs\sample.js [chrome #0-0] Running: chrome [chrome #0-0] [chrome #0-0] search casley [chrome #0-0] √ ようこそ、キャスレーコンサルティングのホームページへ [chrome #0-0] [chrome #0-0] [chrome #0-0] 1 passing (40s) [chrome #0-0]
まとめ
いかかでしたでしょうか。
環境構築はとても簡単で、画面要素の取得方法にさえ慣れてしまえば、テストを実装するのも難しくはありません。
安定したテストシナリオを一度作成してしまえば、無影響確認などの繰り返し実施するテストの工数を削減できます。
テストツールは他にも色々あり、
今回のWebdriverIOのようなブラウザテストツールの他に、ユニットテスト用のツールもあります。
こういったツールでコード化・自動化することで、なるべく楽にテストを実施して、実装に注力できるようにしましょう。
今回はWebdriverIOがメインで、TypeScriptやjasmineにはあまり触れられませんでしたので、
TypeScriptのコーディングやjasmineを使ったテストなどについて、またの機会に書いていければと思います。
最後までお読みいただき、ありがとうございました。