Selenium IDE(2018/12/06現行版)からselenium-webdriverのjsコードに変換する

Selenium IDE(2018/12/06現行版)からselenium-webdriverのjsコードに変換する:

おはようございます、アドテクノロジー部の津久井と申します。

前職は MotecoBeautyというスマホアプリやアドフリくんという国産SSP等の開発に携わっており、

昨年12月にDMMに参画いたしました。


アドテクと自動テストによるQA(品質保証)の関連性

クロスブラウザ・モバイルOS....

ブラウザ / モバイル実機による検証・および自動化は、webサービスやモバイルアプリ開発者のみならず

アドネットワークやSSP等のアドテク界隈でも重要視されています。

参考: QA(品質保証)チームによる実機端末をつかった自動/手動テストの裏側(アドテクセンター通信)

自動化のミドルウェアはいくつか知られていますが、今回はその中から、古くから

ブラウザの自動テストに用いられているSeleniumと、ブラウザ操作の記録ツール

「Selenium IDE」にまつわる子ネタ(表題)を1点ピックアップして紹介いたします。


Selenium IDEの歴史

Selenium IDE自体は2004年(!)よりThoughtWorks社によって開発が始まった自動化フレームワークです。

おそらくエンジニアの方なら公私のどちらかで1度は触れてみたことがあるのではないでしょうか。


スタンドアロンのSeleniumが潰れた!

まず最初に、表題の機能は現行のSelenium IDEには搭載されておりません。

詳しい説明は [2018年時点] Selenium IDE についてまとめてみた にまとめられていますが、Firefox 55から

(旧)Selenium IDEが使えなくなりました。

現在全てを刷新した現行Selenium IDEがブラウザ拡張機能(Chrome,Firefox)で提供されていますが、旧版

に比べ、 さながらLight版程度の機能になっています。(動作を記録して、独自のファイルに保存するのみ)


潰れた結果、コードへの変換が出来なくなった!

前述の刷新でスタンドアロン版で実装されているSelenium IDE -> selenium-webdriverへのコード変換の

機能も消えてしまい、独自の.sideファイル(Selenium IDEのベースとなるSideeXに起因する)での保存のみとなりました。


Selenium IDEで出力した.sideを「Selianize」でコード変換

(本投稿は結局このnpmライブラリを紹介するだけの中身なのですが)

あまり(というかぼとんど)言及されているのを見たことがありませんが、実はSelenium IDEのリポジトリには
Selianizeという selenium-webdriver 用のコード変換用のライブラリが同梱されています。

(単独のnpmライブラリとしても利用可)

今回はこのSelianizeで実際前述の.sideファイルをにselenium-webdriver用のコードに

変換&出力する手順を、以下に記載していきます。


手順

Googleで「まなびストレート」を検索&該当のwikiページから林原めぐみ氏のページに飛ぶ操作を記録します。

(中身自体に意味はありません)

※Selenium IDE自体の記述は最小限操作程度です


事前準備. ChromeにSelenium IDEの拡張

Selenium IDE(Chrome拡張)をインストールしておく

※Firefoxの場合は https://addons.mozilla.org/ja/firefox/addon/selenium-ide


1. Selenium IDEで操作を記録する

割愛 (参考 : https://qiita.com/gluelan2013/items/0513c5331b6a67086308)

※各Commandのリファレンス的なものは、ベースになっているSideeXのページが参考になるかも

操作の自動記録以外に 直接Selenium IDEを操作して手順を追加することも可能です。

sleep / run script の Command などは のこの手段でIDE上から実装を行えます。

1点補足すると、Command によってはSideeXのリファレンス(兼 公式)通り

Targetの引数に 値を入れることもあります。どうも直感的ではないですが......

[たとえば、pauseコマンドに設定するミリ秒はTargetに書く]


スクリーンショット 2018-12-03 16.35.39.png



2. Selenium IDEから.sideファイル(操作手順を記録したファイル)をローカルに保存

記録した手順を、IDEの右上から「Save Project」でから.sideファイルに保存します。


3. 「Selianize」モジュールを読み込み、selenium-webdriverコードに変換するnode.jsの実装を行う

.sideを読み、WebDriverIOコードに変換するnode.jsコード
"use strict" 
 
const selianize = require('selianize').default; 
const fs = require('fs'); 
 
 
(async () => {  
    //.sideの読み込み & JSONをパース 
    const project = JSON.parse( 
        fs.readFileSync('sample.side') 
    ); 
    const selianized = await selianize(project); 
    //変換後のプロジェクトを表示 
    console.log(selianized); 
})() 
上記の実行結果は以下です。

{ globalConfig: 'global.Key = require(\'selenium-webdriver\').Key;global.URL = require(\'url\').URL;global.BASE_URL = configuration.baseUrl || \'https://www.google.co.jp\';let vars = {};', 
  suites:  
   [ { name: 'Default Suite', 
       persistSession: false, 
       code: 'jest.setTimeout(300000);describe("Default Suite", () => {it("AAA", async () => {await tests["AAA"](driver, vars);await driver.getTitle().then(title => {expect(title).toBeDefined();});});});', 
       tests: undefined, 
       snapshot: undefined } ], 
  tests:  
   [ { id: '51404450-7b46-4f36-b443-b56386b206ee', 
       name: 'AAA', 
       code: 'tests["AAA"] = async (driver, vars, opts) => {await driver.get((new URL("/", BASE_URL)).href);await driver.manage().window().setSize(...(`1306x847`.split("x").map((s) => parseInt(s))));await driver.wait(until.elementLocated(By.name(`q`)), configuration.timeout);await driver.findElement(By.name(`q`)).then(element => {element.clear().then(() => {element.sendKeys(`まなびすと`);});});await driver.wait(until.elementLocated(By.css(`div.sbl1 > span`)), configuration.timeout);await driver.findElement(By.css(`div.sbl1 > span`)).then(element => {element.click();});await driver.wait(until.elementLocated(By.css(`h3.LC20lb`)), configuration.timeout);await driver.findElement(By.css(`h3.LC20lb`)).then(element => {element.click();});await driver.wait(until.elementLocated(By.css(`dd > dl > dd > a`)), configuration.timeout);await driver.findElement(By.css(`dd > dl > dd > a`)).then(element => {element.click();});}', 
       snapshot: undefined } ] } 
各要素ごとに、selenium-webdriverのjsコードが文字列として返却されているのがわかります。

globalConfig (初期設定)
global.Key = require('selenium-webdriver').Key; 
global.URL = require('url').URL; 
global.BASE_URL = configuration.baseUrl || 'https://www.google.co.jp'; 
let vars = {}; 
suites[].code (jestのテストコードの雛形)
jest.setTimeout(300000); 
describe("Default Suite", () => { 
    it("AAA", async () => { 
        await tests["AAA"](driver, vars); 
        await driver.getTitle().then(title => { 
            expect(title).toBeDefined(); 
        }); 
    }); 
}); 
tests[].code (実際の動作のコード)
async (driver, vars, opts) => { 
    await driver.get((new URL("/", BASE_URL)).href); 
    await driver.manage().window().setSize(...(`1306x847`.split("x").map((s) => parseInt(s)))); 
    await driver.wait(until.elementLocated(By.name(`q`)), configuration.timeout); 
    await driver.findElement(By.name(`q`)).then(element => { 
        element.clear().then(() => { 
            element.sendKeys(`まなびストレート`); 
        }); 
    }); 
    await driver.wait(until.elementLocated(By.css(`div.sbl1 > span`)), configuration.timeout); 
    await driver.findElement(By.css(`div.sbl1 > span`)).then(element => { 
        element.click(); 
    }); 
    await driver.wait(until.elementLocated(By.css(`h3.LC20lb`)), configuration.timeout); 
    await driver.findElement(By.css(`h3.LC20lb`)).then(element => { 
        element.click(); 
    }); 
    await driver.wait(until.elementLocated(By.css(`dd > dl > dd > a`)), configuration.timeout); 
    await driver.findElement(By.css(`dd > dl > dd > a`)).then(element => { 
        element.click(); 
    }); 
} 
globalConfig は 定型文かなー、と思いきや、開始地点のURLもここで定義されていますね....


4. あとはよしなに

上記のコードを保存なりevalなり


Selenium IDE自体の使い所(現行版)


コミュニケーションツールとして

Selenium IDE(現行版)には 例えばselenium-webdriverでよく使われるスクリーンショット等の

機能は無く、記録したものをそのまま使うには機能不足感は否めません。なので、

・非エンジニアのメンバーに記録してもらう

・操作を再現した.sideファイルを渡す事により、実現したい内容に対するメンバー間の齟齬を無くす

(長ったらしい仕様書を書いた上、それが間違っているという悲劇を防ぐ)

上記のようなコミュニケーションにおける補助的なツールになれば御の字かな....と思います。


javascriptに変換できるのはSelianizeだけ!(知る限り)

実はSelenium IDEと同様の操作記録ツールには 強化版とも言えるKatalon Recorderという

Chrome拡張が存在し、こちらは既にコード出力機能が実装済です。

ただnode.jsによるjavascriptコードの出力は未対応になっており (現在 C# / JAVA / Python / Ruby 対応)、

node.jsのselenium-webdriverによる実装を行いたい場合には Selenium IDE + Selianize を使うのが

ベストかな....と考えています。


その他

現行のSelenium IDE自体もまだまだこれから + Appiumなどのアプリ向け自動化フレームワークは
機械学習を取り入れ始め、なかなか面白い動きを見せているというところもあり、今後の

IDEアップデートに期待しつつ、自動化界隈のアクションをマクロな視点で注視したいところです。


最後に

アドテクノロジー部は今年4年に発足したばかりの組織ですが、松本新CTOの元(明日は松本さんの記事です!)、

2019年は本格的に活動の幅を広げ、飛躍と貢献の流れに繋げられればと思っております!(します)

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)