みなさんこんにちは!
Selenium WebDriverの開発中に遭遇した問題、そのソリューション、およびこれらのソリューションを原則としてどのように使用できるかについてお話したいと思います。 これらはすべてプロトタイプフレームワークの形式で提示され、リンクは記事の最後にあります。
この投稿では、ページオブジェクトテンプレートの実装、テストの実行中に発生したエラーの処理方法、およびロギングについて少しお話します。 また、Selenium WebDriverを使用して実装されたツールの一部とそのベストプラクティスに関する情報も共有します。
私の記事の概要は次のとおりです。
1.エントリではなく、キャプテンの証拠。
2.あなた自身について少し、自己紹介をする必要があります...
3.なぜセレンなのか?
4.ページオブジェクトについて...
5.バグではなく、機能です!
6.また、ロギングとレポートについて。
7.しかし、アナログはありませんか?
8.約束されたリンク。
9.結論として。さあ、行こう!
1.エントリではなく、キャプテンの証拠。

ソフトウェアテストとは何か、どの戦略とモデルが存在するのか、ソフトウェア開発と品質保証のプロセスにおけるその役割と、このプロセスが存在しない場合にどのようなリスクプロジェクトとユーザーがさらされるのかを説明することは意味がないと思います。 さらに、現在のプログラミングは芸術ではなく、何百万人もの専門家にとっての技術です。 プロジェクトは短時間で、限られた予算で実装され、多くの場合、単純に膨大な機能を備えたモンスターになることがあります。 さらに、製品はバージョンごとに集中的に変化する可能性があるため、改善してください。 そして、そのような「改善」はそれぞれ致命的です。
このような状況では、自動テストが重要な役割を果たします。 どのモデル、戦略、および方法が存在するかは、他の情報源で確認する方が適切です。 私の記事はそれについてではありません。 クライアントサイドWebアプリケーションをテストするための自動化ツール専用です。
2.あなた自身について少し、自己紹介をする必要があります...
私は4年前から回帰自動テストを行っています。 製品のデスクトップクライアントと、ビジネスロジックを記述するクラスをテストします。
こちらのプロジェクト
で使用されているツールについて読むことができ
ます 。 この間、多くのUIテスト、単体テストが自動化され、多くのことが行われました...テスト自動化の進化を観察したのはここです。それに参加しました。

最初は、これらは自動記録ツールを使用して膝の上に直接記述されたスクリプトであり、スクリプトのロジックはテスト対象オブジェクトと対話する方法と切り離せませんでした。 テストのセットが増加するにつれて、何らかのフレームワークを開発し、それを自動スクリプトに使用する必要があることが誰にでも明らかになりました。 テスト対象のアプリケーションの誰もが、テスト実行全体に対して非常に悲しい結果をもたらしました。
さらに、製品やデータベースと対話するためにプログラムインターフェイスを使用する必要がありました。ダイアログフォームが示すものでは不十分だったためです...
しかし、私は夢中になったもの。 しかし、効果的な自動検証のために開発者の製品とのやり取りの戦略と戦術を
最初から考え直すことがいかに重要かを実感したのはまさにここでした。
盲ろう者または南極大陸のどこかで生まれて住んでいる人は、アプリケーションがデスクトップクライアントからWebクライアントに移動する傾向に気づきません。 はい、Webの開発は現在主流であり、秘密ではありません。
フロントエンドの機能テストを自動化するために使用される何かを学び、さまざまなクライアントプラットフォームとの互換性をチェックするために、私は自由に時間を取らないことにしました。 さらに、プロジェクトのWebクライアントが...
私はSelenium Webdriverを選びました。
3.なぜセレンなのか?

なぜセレン?
むかしむかし、それは使用されたWeb開発の世界からの必死の愛好家だけが使う小さなツールでした。 今では、世界中の何千人もの自動化エンジニアが欠陥と戦うためにサービスを開始しただけでなく、フロントエンドの開発者でさえも手ごわい武器です。

Selenium製品ラインについては、
こちらまたは
こちらをご覧ください 。
しかし、これは
直接自動化されたテストの手段では
ないと言う必要があり
ます 。 たとえば、Selenium Webdriverには、ブラウザとそのウィンドウに読み込まれたコンテンツとのユーザーの対話をエミュレートするための多くのソフトウェアツールとインターフェイスが用意されています。 これらの資金は、そのような相互作用の可能なオプションのほぼ100%をカバーしています。 これはすべてより広い用途を見つけることができます。 しかし、たとえば、デフォルトでは、特定のテストの合格に関するレポートを生成できません。
さらに、他にもいくつかの問題があります。 以下はその一部です。
WebDriverおよびWebElementインターフェイスは 、非常に限られた機能を提供します 。 主に、アクティブなページの要素を検索し、要素に対して最も単純なアクション(値の入力、クリックなど)を実行することを目的としています。
HasInputDevices、Locatable、Options、Alertなどのインターフェイスによって、他の多くの便利な機能が提供されます。 また、
WebDriverと
WebElementのみを使用すると、自動テストの機能
が大幅に制限されます。
各ブラウザには独自のドライバがあります。 現在は次のとおりです。
ChromeDriverFirefoxDriveHtmlUnitDriver (ユニット用
-htmlドキュメントのレベルでのテスト);
InternetExplorerDriveOperaDriver ;
RemoteWebDriver (私のお気に入り、リモートマシンでテストを実行するのに適しています);
SafariDriverIphoneDriver ;
AndroidDriverPhantomJSDriver (一部のエキゾチックなブラウザー、マシン上でビルドするのに我慢できませんでした)。
Yandexチームもドライバーをすぐにリリース
すると思います。
あらゆる好みとあらゆるニーズに対応する幅広い選択肢。 しかし、テストプロジェクトで上記の1つまたはいくつかを明示的に使用すると、ブラウザーからブラウザーにすばやく切り替えるか、一度に複数を使用する必要がある場合に問題が発生します。
したがって、希望するインスタンスを作成するための単一の方法またはインターフェースが必要です。 常に変更可能な何らかの設定をパラメーターとして受け入れることが望ましいです。 この設定には、ブラウザの種類、
機能 、
タイムアウトを含める必要
があり
ます 。 さて、ハードコーディングする機会を与えましょう。
ページとのインタラクティブな作業を担当するクラスを作成します。 PageFactoryは素晴らしいツールです。 ただし、非常に大きなページを記述するクラスのコードの可視性が失われるため、その使用は不便になり、繰り返し要素にはコピー&ペーストが大量に含まれます。 方法は、別々のブロック(クラス)で繰り返し要素を選択し、すでにブロックを使用することです。 しかし、これは問題を最後まで解決しません。 個別のタブまたはブラウザウィンドウでページを開くことでサービスが機能する場合、これらのウィンドウにはすべて重複したブロックがありますか? また、それらのいくつかはフレームにあります! 私は
これと
これを実験し、すぐに説明した問題にぶつかりました。 そして、状況は、WedDriverを実装するインスタンスがアクティブなページ(ウィンドウ/タブ)またはフレームのみを見るという事実によって悪化します。
driver.switchTo()。Window(somehandle)または
driver.switchTo()。Frame(frameIdentity)を呼び出さずに、ページをブロックに分割して、作業テストで記憶して直接操作できるようにしたいと思います。
したがって、私は上記のツールを習得するだけでなく、プロジェクトを作成するために、さらに良いことに、Selenium Webdriverに基づくプロトタイプフレームワークを作成するためにタスクを設定しました。 さらに、類似物を見つけて、それを簡単に統合できるようにしてください。 タスクがそのようであれば、提出された資料ははるかに簡単に吸収されると思います。
言語としてJavaが選択されました。 開発環境-Eclipse。
この道がどのように徐々に克服されたかについては語りません。 私は問題とその解決策の説明を続けたいと思います。 たぶんアメリカは開かないだろうが、誰かが自分に役立つ何かを見つけたら嬉しいだろう...
4.ページオブジェクトについて...
デザイン-ページオブジェクトパターンについて知らないようなオートマトンはほとんどないと思います。 ところで、このパターンは、一部のデスクトップアプリケーションのUI自動テストの作成にも適用できます。 しかし、Webインターフェイス用のJavaでの実装について説明します。
レセプションについては
こちらをご覧ください 。
次に、あまり成功していないテストの現在動作中のコードを紹介します。
コードどこかで1つの入力を行い、2、3回クリックする必要があるスクリプトを記述したい場合、誰もが良いことを理解していると思います。 何かが
正しく (!!!)変更された場合、このようなテストをすばやく修正できます。
テストで上記の手順よりも多くをチェックする必要がある場合、読み取りに不便なコードシートが判明します。 それでは、このすべてに巨大なテストプロジェクトを掛けましょう。 Googleを変更するたびに、貧しいテスターがどのように泣くのか、何が彼を支えているのかを想像しましたか? そして、彼がそのように泣かないように、ページでテストがアクションを実行するクラスが必要です。 また、何かが変更されたとしても(この変更はバグの導入ではなく機能です)、編集はプロジェクト全体ではなくローカルで行われます。
あなたのプロジェクトを含め、Page Objectの実装はたくさんあります。 以下に、実装と同じテストを示します。
パブリックインターフェイスIPerformsClickOnALinkパブリックインターフェイスIPerformsSearchパブリッククラスSearchBarパブリッククラスLinksAreFoundパブリッククラスAnyPageパブリッククラスgoogleテストそして、あなたが一生懸命働いて
このセットアップのようなことをするなら、
テストはこのように働くかもしれません 。
多くの経験豊富な自動化エンジニアは、おそらく次のように考えていました。「ええ、はい、Page Factoryは... まあ、おそらくいくつかのあいまいな注釈が登場しました... @PageMethodが呼び出されます。 PageクラスとEntityクラスの子孫...
ここでも同様のことがわかり
ました 。 著者、私たちは皆これを見ました!”
ええ、はい。 これは簡単な例です。 メインページの説明を意図的に複雑にして、同じページの説明を2つの独立したクラスに分割できることを示しました。 このアノテーションについて以下で説明します...
そして今、例はより複雑です...
写真はいくつかの状況を示しています。

テストの内容:
1はdocs.google.comに移動します
2アクセス可能なGoogleドキュメントを開きます
サービスのメインページの3は、共有設定ダイアログを呼び出します。
4開いているドキュメントから同じダイアログが呼び出されます。
明確にするために、アクションのシーケンス全体をスクリーンショットの形式で示しています。 ハイライトされたアクティブなアイテム:




必要性:何らかの方法でこのダイアログの両方のインスタンスを異なるウィンドウで処理します。 そして、これが私に起こったことです。
これは、説明されている前提条件です。次に、名前、メールアドレスなどを入力するように求められるフィールドをクリックします。表示されるポップアップ要素で[キャンセル]をクリックし、その後[完了]ボタンをクリックします。 アクションは両方のウィンドウで実行されます。 明確にするために、以下は写真形式のシーケンスです。


そのため、私たちはこのタスクに楽に対処しました。 。
これは、ドキュメントとメインページ
のgetCustomizingAccessDialog()メソッドのコードです 。
つまり フレーム内に配置された要素のポップアップブロックがあり、独立して存在し、必要に応じて取得されるオブジェクトとして使用します...それはドキュメントのページとサービスのメインページにあり、それらから取得されます。
実際、私は長い間、このテストオブジェクトをさまざまなソースで整理して説明するための最良の方法を探していました。 でも、たぶん私はひどく見ていました...
明らかに、再利用のためにページ要素をブロックにグループ化する必要があります。 これらのブロックは、独立したオブジェクトを装って外部に転送することもでき、それらを直接操作できます。 これが行われない場合、クラスは属性とメソッドの数を増やします。
分解が必要です。 それ以外の場合、これらのオブジェクトを取得します。

上記の例を見ると、メインコンテンツを操作する方法に、各種類のポップアップダイアログを操作する方法が追加されています-アクセス設定、名前変更のモーダルフォーム、オプションの選択、ドキュメント内のコメント。
単一のブラウザーウィンドウ(単一のタブ)に読み込まれているものをテストする場合、上記のソリューションは簡単に実装できます。
ただし、説明されているかなり複雑な動作の場合、目的のフレームに切り替えることを忘れずに、ページからページに何らかの形でWebドライバーを切り替える必要があります。
そして、アイデアが浮上しました!
しかし、そのような各オブジェクトに自分自身へのパスを記憶させ、ページとの対話型対話のメソッドを呼び出すときにwebdriverを自動的に切り替えるように教えたらどうでしょう。これは、「ページ」の概念からいくぶん離れれば、可能だと思われます。 つまり それによって、私はダウンロードされたコンテンツではなく、コンテンツがロードされたブラウザウィンドウを意味します。 このウィンドウには一意の文字列識別子があり、これにより他のウィンドウと簡単に識別できます。 オッケー! つまり、メソッドを呼び出す前に、目的のウィンドウへの切り替えが発生します。
だから フレームをどうするか? また、要素の各ブロックがどのフレームに切り替えるかを追加で確認することもできます。
だから私は道を作っています。
私がPageと呼んだクラスのコンストラクターのリストからわかるように (名前は非常に条件付きで、おそらくクラスの名前を変更する必要があります)、ロードされたページの説明を全体または一部で記述し、それに類似する別のオブジェクトを親(親)として示すことができます)必要な場合。 したがって、要素ブロックのリンクグラフを作成できます。 階層のようなものかもしれません。

オッケー! さて、示されたパス、構築された階層。 次は? フィールド内の行をクリックまたは入力するなど、通話中に自動切り替えを実装する方法は?
スイッチング自体はこの方法で実装されます。しかし! 多くの人が質問をするかもしれません:「各メソッドでそれを再度呼び出す必要がありますか?」 以下に、その仕組みを説明します。
私の決定では、コンストラクター自体によって作成されたオブジェクトではなく、それらの代替(プロキシ、言い換えれば)を使用することを提案します。 これには
cglibライブラリが使用されました。 さらに正確には、呼び出されたメソッドをインターセプトする
MethodInterceptor 、プロキシオブジェクト自体を作成する
Enhancer 、および
Callbackです。 上記のタイプを使用すると、将来、各ページの子孫(
java.lang.reflect.Proxyを参照)のインターフェースのセットを作成する必要がなくなり、実装がより柔軟になります。 ただし、制限があります-Pageクラスの継承者は
finalであってはなりません!!!
つまり Page-オブジェクト(Pageクラスの継承)の1つまたは別のメソッドを呼び出そうとすると、このメソッドがインターセプトされ、オブジェクトは自分自身に「切り替わります」。 そしてその後、メソッド自体の実行。
いいね! しかし、この種のインターセプトは、各メソッドが呼び出されたときに起こりますか? 質問は公平です。 Page-オブジェクトもJava言語オブジェクトであることを忘れないでください。 このようなオブジェクトには、ブラウザの対話性に関連付けられていない
publicメソッドまたは
protectedメソッドが含まれている場合があります。 になる方法 明らかに、メソッドを、対話型の対話を行うメソッドと他のすべてのメソッドに分割する方法を考え出す必要があります。
@PageMethodアノテーションはそのような「セパレータ」として機能します。 つまり、メソッドがそのようなマーカーでマークされている場合、ページまたはそのフラグメントへの予備切り替えが実行されます...
一般的に、ソリューションは次のようになります。次に、ページ-オブジェクトを作成する可能性について少し説明します。
要素またはページプレゼンテーションのブロックは、主に3つの方法で作成できます。
-Entityクラスの子孫から -これは、一般にメインページまたは他のページで開いているサービスのモデルのようなものです。 説明されている例では、これはGoogle(検索エンジン)、GoogleDocsApplication(Googleドライブ)です。 ちなみに、Googleの例では、「アプリケーション」を使用して、原則として、Page-オブジェクトと同様に作業できることを示しています。 パネルと検索結果に要素を含めました。
「Essence」は、サービスの最初の(メイン)開いているウィンドウ/タブにあるオブジェクトを生成できます(Googleドライブの例、「
docs.getContent(); 」-これらのメソッドの1つをラップし、Googleの例-「
searchBar = get (SearchBar.class); ”-これらのメソッドのいずれかの呼び出し)または新しく表示されるウィンドウ/タブに存在するもの(
AnyGoogleDocument anyDocument = docs.get(AnyGoogleDocument.class、1) ;)。
この図は、Entityクラスのメソッドのリスト全体を示しています。これらのメソッドは、すでに使用する準備ができているか、継承者で重複する可能性があります。
-Pageクラスの別の子孫から。 つまり...使用可能なGoogleドライブドキュメントのリストがあり、その上でさまざまなアクション(オープン、タグの挿入、ポップアップメニューの操作、アクションバー上のボタン)を実行します。 これらすべてを個別のクラスで説明します(上記の例-GoogleDocsMainPageContent)。
これらのアクションの結果として表示される要素(アクセス設定ダイアログ、さまざまなモーダルフォームなど)は、このページの一部です。 しかし、それらは機能的にはそれから隔離されているかのように考えることができます。
このような要素は、Pageの個別の継承クラスで説明できます。
同様に、便宜上、より大きく、より静的なブロック(テーブルエディターやドキュメントエディターなど)を記述することができます。
説明されているすべての状況で、指定された親を使用してオブジェクトを作成できます。
この図は、Pageクラスのメソッドのリスト全体を示しています。これらのメソッドは、すでに使用する準備ができているか、継承者で重複する可能性があります。

テスト用に上記のオブジェクトを作成するためのすべてのメソッドは、スクリーンショットのクラスメソッドのラッパーです。
-TestObjectFactoryを使用します 。 これまでのところ、この方法は、サービスを使用せずに独自に機能できるコンポーネントがある場合に適しています。 たとえば、ドキュメント、スプレッドシート、プレゼンテーションなど。 アクセス権とドキュメントへのリンクがあれば、サービスの助けを借りずに開くことができます。 そのような状況だけを確認する必要がある場合は、確認できます。 次に、2番目のユースケースが繰り返されます。 しかし、このオプションはこれまでのところ最も機能していません。
このシステムの基本的なメカニズムとジョークについて話すことができました。 しかし、この章は非常に大きくなります。 これは、別のメモの主題である場合があります。
5.バグではなく、機能です!

自動テストの実行中に発生する例外は、問題を通知します。
これは、開発者のバグのシグナルである可能性があります。 テスト自体の記述は不十分です。 そして、この悲鳴はすでに修正されているはずです。 ツール自体も例外ではありません。 Seleniumの欠陥のリストは
ここにあります 。
しかし、これは私が話していることではありません。
この状況はいかがですか? たとえば、手動テストの段階で欠陥が検出されました。 これはバグトラッカーにリストされており、「マイナー」である可能性があります。 このバグはユーザーにとって致命的ではなく、簡単に回避できます。 現時点では、開発者にはより重要なタスクがあり、この欠陥の修正はより良い時期まで残すことができます。 そして今、回帰テストが必要です。そのパスは、説明されている欠陥を通り抜けます。 テストが書かれた、そして...なんてこった! バグの原因となった恐ろしい例外でクラッシュします。
状況は、私はあなたに言いますが、快適ではありません。 最善の方法は、エラーをキャッチしてテストを最後までパスできるような松葉杖を作ることです。 そうしないと、ひどいことが起こる可能性があります-テストはこの重大でないエラーに到達するだけで、落ちて残りをチェックしません。 そして、そこにある種の悲嘆が登りました-開発者とそこに混乱を作り出しました。 しかし、「クランチ」を書くと、テストスクリプト自体や、テスト対象を記述するクラスが複雑になる可能性があります。 この欠陥はすでに修正されていますが、「松葉杖」を忘れることがあります。 やがて、プロジェクト全体がこれに似たものになる可能性があります。

さらに悪い状況があります...
主な例は、
StaleElementReferenceExceptionの発生です。
詳細はこちらをご覧ください 。 これは、使用するツールが単に設計されていない処理に対して、テストされたアプリケーションの通常の動作中に状況が発生した場合の例です!
たとえば、Googleドライブドキュメントのリストとスプレッドシートドキュメントの「テスト」を作成しようとしたときに、これに遭遇しました。 この図は、このような例外が最も頻繁に発生したアクションを示しています(強調表示された緑の要素をクリックします)。

「アスタリスク」の値を変更した後、「テスト」のさらなる通過は地雷原を通る旅のようでした。 「スター」を元の状態に戻そうとしたとき、または左側にあるチェックボックスを使用しようとしたとき、および場合によってはドキュメントを開こうとしたときにエラーが発生しました。
このエラーに対処する方法はいくつかあります-
同じアクションの再実行(アイテムの検索とアクションの実行)からマシンの仮想メモリの増加まで。 オッケー! 私ができない2番目のと仮定します。 それから、最初のものは私のために残っています。
リストを操作する方法は次のようになります(+可能なバリエーション):
試してみる
{
//いくつかのアクション
}
catch(StaleElementReferenceException e)
{
//同じアクションをもう一度
}
はい、動作します。 しかし、このように記述された各メソッドでクラスを維持するのは簡単ですか? そして、それがテストされた機能で観察されたら?
Googleドライブを「テスト」しようとする前に、決定は熟していました。
ITestObjectExceptionHandlerインターフェースを思いつきました。 そして、 これはそれを実装する抽象クラスです 。 可能な例外処理のプロセスを簡素化するために、コンストラクターとthrowableList属性が追加されました。 クラスオブジェクトを継承する目的は、例外を処理して値を返すか、新しい例外をスローすることです。
次。
前に説明したPageおよびEntityクラスに戻ります。 これらにはクラスがあります- これらの属性を持つ祖先。 PageおよびEntityのインターセプターの祖先には、 このような実装があります。 繰り返しになりますが、 これはインターセプターがPageクラスとその子孫に対してどのように機能するかを思い出させます。必要なものは強調表示されます/ ** / 。 Entityクラスの実装は非常に似ています。
.., . , , . , , .
Google Drive , , , StaleElementReferenceException. , Google Drive, .
: StaleElementReferenceException . (!). , Google .
, - , .
たとえば。 :
1. Google Drive
2.
3.
4. «»
5.
, , :





.

, - , , . , . : UnhandledAlertException. - , . , . , , , .
, :
1. ( ) ;
2. .
, , .
:
1. .
2. ( ) .
: . : FAILED TESTS BUT WITHIN SUCCESS PERCENTAGE. :

(!!!). . , , .
6. .



キャップを短時間オンにします。 おそらく、誰もが、テストに直接合格することに加えて、製品の現在の状態を判断できるおかげで、何らかの排気が必要であることを理解しています。 さて、またはテストに合格するための詳細が必要です...これらのタスクは、ロギングとレポートを解決するだけです。
実験にjavaを使用したため、ロギングに適切なフレームワークを選択すると頭が痛いです。 そして、たくさんの選択肢がありました! この記事の著者は、javaでのログインの状況を非常によく説明しています。 そして、最初は私自身が何を受け取りたいかわからなかった。 さらに、このログを使用してレポートを作成できる必要があります。
要約すると:
-メッセージ、レベル、コンソールへの出力データを記録できるシンプルなロガーが必要です-少なくとも。
-例外のオブジェクトが発生した場合、例外のオブジェクトに「固執」できるのは非常に良いことです。
-そして非常に良い-テスト中に判明したファイルへのリンクをログエントリに添付する機能。
-特殊効果付きのビデオを作成します。
最初の2つのポイントですべてが明確になったと思います。 第三に。 ファイルには、あらゆるもの、xmlファイル、入力されたテキスト、またはブラウザウィンドウから取得したスクリーンショットを使用できます。 これは、たとえばログエントリを処理する場合に便利です。
レポートについて:
-1つのテストの実行中と、テスト全体の起動後の両方で生成されるレポートが必要です。
-このレポートでは、選択したテストで実行された手順の説明を確認したいと思います。
-そのような詳細には、スクリーンショットまたはその他の視覚情報を表示できることが望ましい。
テスト自体を実行するためのフレームワークとしてTestNGを選択したことを忘れないでください。 なんで? まず、テストレポートを生成する機能があるためです。 しかし、より詳細な調査の後、 mavenとantとの統合性 、 jenkinsやhudsonなどの継続的統合システムで使用できる機能、マルチスレッド作業など、他の多くの利点があることに気付きました。 興味がある人は誰でもドキュメントを見ることができます。
しかし、私は気が散っている何か...
ロガーとして、 java.util.logging.Loggerを使用することにしました。 なんで?
-1.4以降のすべてのJavaで、プロジェクトへの余分な依存関係は無用です。
-ブラウザログとの統合は簡単です(Mozilla Firefox、他のブラウザのログ抽出はまだ実装されていません)。
-他のロギングライブラリ(たとえば、 log4j 、 slf4j 、 logbackなど)を使用する場合、ロガーにメッセージを送信することは常に可能です。
しかし:
-ロガーの明示的な初期化を取り除きたい。
-複雑なユースケースがあります-メッセージ階層を構築します。 原則として、デバッグ情報に対応する必要のある多数のレベル-FINE、FINER、FINEST ...不要なすべてを何らかの方法で遮断する必要があります。
-選択したロガーと上記のロガーは、メッセージにファイルを添付できません。 これは、FileHandlersなどの問題ではありません。
今決定。
私のプロジェクトでは、短く明確な名前のクラス-Logを作成しました。 彼の主な方法は次のとおりです。
-debug(String) -FINEレベルのメッセージを生成します。デバッグ目的で使用することをお勧めします
-エラー(文字列)-重大レベルのメッセージ、重大なエラーに関するシグナルを生成します。
-メッセージ(文字列) -INFOレベルのメッセージを生成し、通常の状態に関するシグナル。
-警告(文字列)- 警告レベルのメッセージを生成し、考えられる問題に関するシグナルを生成します。
-log(レベル、文字列)- これらのレベルのいずれかでメッセージを生成したい人のために。
キャッチされた例外のオブジェクトとして追加のパラメーターを持つ同じメソッド:
-デバッグ(文字列、スロー可能);
-エラー(String、Throwable);
-ログ(レベル、文字列、スロー可能);
-メッセージ(String、Throwable);
-警告(文字列、スロー可能)。
さらに(注意!)、ファイルをリンクしてログを書き込む機能を持つメソッド:
-デバッグ(文字列、ファイル);
-エラー(文字列、ファイル);
-ログ(レベル、文字列、ファイル);
-メッセージ(文字列、ファイル);
-警告(文字列、ファイル)。
実際、これらはすべてjava.utils.logging.Logおよびjava.utils.logging.LogRecordの単純なラッパーです。 これらはすべて、プロジェクト内のどこからでもアクセスできる静的パブリックメソッドです。
使用例 コメントの代わりに使用できます。 しかし、あなたはこれで誰かを驚かせるでしょう。
それでは、ファイルをログに「フック」するにはどうすればよいですか? 実際、このロガーはLogRecordオブジェクトではなく、その子孫を作成し、 LogRecWithAttachと呼んでいます 。 すべてがシンプルです! 「祖先」との10の違い、5ポイント、カルマの増加を見つけた人。
オッケー! しかし、誰かがすでに質問を持っているかもしれません:「著者、なぜあなたはそのような過剰が必要なのですか?」
まあ、まず、私が実装したい重要な機能の1つは、ページからスクリーンショットを撮ることでした。 スクリーンショットは、ログやレポートに追加できると思います。 便宜上、ログエントリに写真ページへのリンクが含まれていると良いと思います。
スクリーンショットを撮る機能は、Photographerというクラスによって実行されます。 彼の方法のリストはここにあります:

その機能は次のとおりです。
1.アクティブなページからスクリーンショットを撮り、ファイルに保存します。
2.必要な重要度のログエントリを作成し、保存したスクリーンショットへのリンクを追加します。
3.おそらく、WebElementが一部のメソッドのパラメーターとして指定されていることに気づいたでしょう。 これらのメソッドは、ページ上の要素を強調表示し、写真を撮り、要素を元の状態に戻します。 そのようなスクリーンショットの例は以前に示されました。 さらに、バックライトの色は、ページの選択されたフラグメントの状態の「正確さ」に依存します。 そのため、スクリーンショットは間違った(タイプの)状態を示しています。

内容が正しくないドキュメントのリスト(「テスト」条件では、テキストドキュメントとMS Accessデータベースをロードしないでください)は明るいオレンジ色で強調表示されます。 このような写真は、Photographer.takeAPictureOfAWarningメソッド(WebDriver、WebElement、String)の呼び出しの1つによって撮影されました。
確かに、1つ(!!!)あります-要素はjavaScriptを使用して選択されます。 スクリーンショットに要素の座標を投影するというアイデアがありました。 うまくいきました。 ただし、フレーム内にある要素やスクロールのあるページに配置されている要素の場合、そのような投影(円で囲まれた領域)はオフセット付きで取得されました。 私はその考えを捨てなければなりませんでした。 しかしその一方で-今では特殊効果を使ってビデオを録画する機会があります!..
一般的に-私の写真家はログを補足します。
2番目の、悪くない機会は、原則としてファイルを添付することです。 たとえば、蓄積されたメッセージに基づいてドリルダウンを表示するレポートでファイルへのリンクを見つけるのは本当に悪いですか? たとえば、上記の例からGoogleドライブにダウンロードされたもの。 このリンクをクリックして、表示用に開きます。
そのため、1つ以上のテストの通過に関する運用レポートの作成にスムーズに移行しています。
まず、上記の機能を考慮してログを変換する必要がある場合、 IlogConverterと呼ばれるインターフェイスを思い付きました 。
そして、ここに使用例があります。 たとえば、log4jライブラリーを追加で使用します。 このロガーにファイルデータが必要です。 着信メッセージに添付ファイルがあるかどうかをチェックするオブジェクトを持つクラスを作成できます。 存在する場合、追加のlog4jメッセージが生成されます。 そして、このオブジェクトがログを「聞く」ことができるように、私はそのような方法を提案します-ログ。 addConverter(ILogConverter)。 このメカニズムは、 このコードのおかげで機能します 。
そして、これは新しいメッセージが表示されたときに何が起こるかです:
convert.convert(rec);
私のフレームワークには、TestNGレポートの詳細を生成する名前付きインターフェイスの「標準」実装のようなものを作成しました。 彼女のConverterToTestNGReportを呼び出しました。 彼女は何をしているの? 特定のhtmlテンプレート(これまでに最終属性としてハードコーディングされていた)に従ってログからメッセージをインターセプトし、レポート行を形成します。
Reporter.setEscapeHtml(false);
Reporter.log(htmlInjection);
さらに、メッセージにスクリーンショットが添付されている場合-他のファイルが「<a href = \」の場合、「<img src = \」に変換します。 確かに、ファイルへのリンクのみがあります。 今のところ、何らかの理由で、これらのリンク上のファイル自体は開きません。 しかし、私にとっては(!!!)これで十分です。
結果は、次のレポートのスニペットです。 これらはカスタマイズされたレポートではないことに注意してください。






もちろん、それは失礼かもしれませんが、初めてそうなります。 TestNGレポートの詳細をカスタマイズできるかどうかを理解する価値があると思います。 その場合、そのようなカスタムを作成し、ハードコーディングされたテンプレートの代わりに使用できます。
そしてこれまでのところとても良い。 しかし、それだけでは十分ではありません。 説明します...
オッケー! 使いやすいロガーがあります。 レポートを作成できるツールもあります。 ただし、合格したテストのステータスがログメッセージの最大レベルと同期していることを確認する必要があります。
説明します。 何もしなかった場合、テストが最後まで合格し、失敗しなかった場合、テストのステータスはSUCCESSになります。 実行中にキャッチされない例外が発生した場合、テストのステータスはFAILUREになります。 テストが依存しており、定義テストがパスしなかった場合-SKIP 。 次に、「実行中に何かが発生した場合に、警告または重大レベルのエントリがログに記録されたために、テストが完全に合格したと見なすことは可能ですか?」という質問を考えてみましょう。 つまり、合格したテストのステータスはSUCCESSですが、詳細を見ると、黄色と赤の線が表示されています。 これは少なくとも誤った情報だと思います。
私の解決策は以下です。
テスト自体にスレッド(およびTestNGがマルチスレッドをサポート)を関連付けるクラスを実装しました。 次に、特定のテスト( ITestResultを実装するクラスのインスタンス)を参照してログメッセージが保存されます。 この時点で私は停止しません。 ログメッセージがテストにどのようにリンクされているかを示します。 前述のConverterToTestNGReportのオブジェクトによって生成されます 。 最後に、次のようなクラスとしてITestListenerインターフェイスを実装しました。
-テスト(テストメソッド)の実行を開始する前に、ConverterToTestNGReportのインスタンスをリスナーとしてログに追加します。
-各テストメソッドの実行後、ログの記録された事実と通過のステータスを同期します。
1.テストが最後まで合格したが、ログにSEVEREレベルのメッセージがある場合、その通過のステータスはFAILUREに変わります。
2.テストが最後まで合格し、SEVEREまたはWARNINGのレベルのメッセージがなかった場合、そのステータスは変更されません-SUCCESS 。
3.警告レベルのメッセージが記録された場合、ステータスをSUCCESS_PERCENTAGE_FAILUREに変更することをお勧めします。 または、「ユーザー」に自分に適したステータスを選択させます 。
そして今、フィナーレ!
上記のレポートを作成するには、次のアクションを実行する必要があります。
@Listeners({ReportBuildingTestListener.class})
パブリッククラスNewTest {
この章の結論として、ロギングはすでにほぼ自動化されていると言いたいと思います。 つまり 値の入力(入力の前後)、クリックと送信(アクションが完了する前)、新しいタブ/ブラウザウィンドウの外観、リンクをクリックした結果-インタラクティブなアクションがグラフィカルに記録されます。 それ以外の場合は、いくつかの「標準」テキストメッセージが生成されます。
これらの機能の一部はクラスによって引き継がれます。クラスは、Seleniumを構成するツールと上位レベルのクラスの間のレイヤーです。
これは、 ExtendedEventFiringWebDriver - EventFiringWebDriverの子孫であり 、実際にすべての汚れた作業を行います。 その「乾燥」は、ネストされたクラスとしてのWebDriverEncapsulationの一部であるIExtendedWebDriverEventListenerインターフェイス(拡張WebDriverEventListener ) の実装によって実行されます。 WindowSwitcherとSingleWindow 、ブラウザーウィンドウ/タブマネージャー、およびウィンドウ/タブ自体の表示は、ロギング機能の一部を引き継ぎます。
ロギング自体は、プロジェクト全体に対して構成できます。 ただし、構成とこれらのクラスについては、別の記事でお話ししたいと思います。
7.しかし、アナログはありませんか?




だから! タスクの1つは、類似体を見つけて、それらを操作しようとすることでした。 これは心を広げます。 さらに、多くの便利な機能が既に実装されています。 そして、なぜ同じことをする自転車を書くのですか? とにかく、うまくいきません! 必要な機能がどのように実装されているかを確認し、それらの使用方法を学ぶと、はるかに役立ちます。
しかし、実際には、類推は何ですか?
私が絶対に実装することを拒否した機能は、クラスが何らかの形でWebElementを実装するオブジェクトで動作します。 つまり 私はこの方向に何もしないことにしました ビデオに出くわしました- この素晴らしいフレームワークに関するレポート。 むしろ、実際に試してみることに興味が生じました。 Googleドライブでの実験中に完全に成功しました。 そして、手間をかけずにyandex-qatools htmlelementsとの相互作用を確立することができました。 たとえば、 これは、このデモプロジェクトのすべてのPageオブジェクトが継承される抽象クラスのコンストラクターの外観です。 しかし 、すべてのGoogleドキュメントの一般的なプロパティを記述するクラスのこのような属性のセットを取得しました。 ここにWebElementが表示されますか? ページフィールドを説明するすべてのタイプされた属性、およびそれらのいくつかは、名前付きライブラリのパッケージに含まれているものです。 必要な要素の一部がそこにありませんでした。 しかし、このツールを使用して簡単に説明できました 。
さらに、これらすべては、私が置いていた機能を犠牲にすることなく可能でした。 まったく逆です。 前に説明したページの説明の分解は、さらに視覚的になりました。 これは双方にとって好都合な状況です!
ページ上のフィールドを操作するための別の興味深い手法は、thucydidesフレームワークに実装されているPageObjectクラスの継承者の例を使用して提示されます (詳細は後述)。
したがって、この方向で無駄な仕事をしないことを支持する議論は十分すぎるほどです。
私の「研究」の過程で、私は別のツールに出くわしました -すでに言及したツチジド 。 彼についての記事を読んで、リポジトリを見て、何かを書こうとして、私は彼の能力を使って何とか彼と友達を作ることが最善であるという結論に達しました。 そして私を信じて、これには多くの理由があります:
-自動テストの段階的な構成。
-単に動作するコードとしてではなく、 JBehaveフレームワークを使用してスクリプトを記述する機能 。
-ページを操作するための便利な方法とツールのセット。
-JIRAおよび他の課題追跡との統合 。
-レポート。 カバーについて。 物語。 等
1。 
2。 
3。 
実を言うと、私はツキジデスと組み合わせて2つ目のデモプロジェクトを作成することを考えていました。 十分な時間や熱意がありませんでした。 しかし、おそらく私は彼に戻ってくるでしょう。 アイデアを共有し、それがどの程度実現可能かを知りたいだけです。 そして、私が何を実装したかについて説明します。
- 「クロスドライバ」を実装しました 。
-1つのテストで複数の開いているブラウザーで動作する機能。
- 構成可能性を実装しました。
使用するブラウザー、機能パラメーター、タイムアウト(Webdriverの待機タイムアウト、独自-新しいウィンドウ/タブの待機時間に関連して、それらを切り替える)を指定して、プロジェクト全体に対して1つの設定を行うことができます。
一般的な設定と部分的に重複する可能性のある追加/個別の設定を行うことができます。
つまり -一般に、ブラウザ、その機能/設定、およびタイムアウトのセットが示されます。 さらに-ブラウザーと機能のみ。 この設定を使用して新しいWebdriverインスタンスを作成すると、指定されたブラウザーが開き、必要に応じて構成されますが、タイムアウトは一般的な設定から取得されます。
これは、たとえば、テストをパラメーター化するために使用できます。 TestNGのパラメーター化の例 。 私の例 。
- コンテンツを参照せずにブラウザウィンドウ/タブを管理するメカニズム(必要なページの読み込みを含む)。
-Webdriverインスタンスを最高レベルで非表示にするツールのセット 。 すべての作業はそれらを通して行われます。 利点は何ですか-HasInputDevices 、 Options 、 JavascriptExecutorなどのインターフェースの使用に関連するすべての汚い作業 すでに完了しました。 例。
理にかなっている場合は、別の記事で上記について説明します。
-4および5で説明されているインタラクティブな相互作用を実装するオブジェクトを編成する方法。
-6で説明したロギングと、TestNGレポートの例を使用してレポートを作成する方法。
上記からわかるように、私はWebDriverと関連コンポーネントの操作に集中しようとしました。
この点に関して、ツキュディドにはないもの(さらに遠くの印象のある印象):
- 開いているページのマップを追跡および構築する機能。 PagesおよびPageUrlsクラス 。 リンクに直接移動したり、前後に移動したりすることしかできません。
- 要素を操作するためのツール、追加の期待値セット 。 PageObject 。
そして今、一般的なアイデア:
1.メカニズムを使用してブラウザを開きたい。
2.前述のEntityクラスの子孫のオブジェクト-Pagesオブジェクトのラッパー。 したがって、両方のクラスの機能を組み合わせようとします。
3. Page(第4章)クラスとPageObject(thucydides)クラスの継承の機能を何らかの方法で組み合わせることができます。
4.番号3のレポートに戻りましょう。ご覧のとおり、ステップは非常に大きくなる場合があります(最初のステップには1分かかり、30秒以上あります)。 確かにこれらはアトミックなステップではありません。 このレポートに表示されるスクリーンショットは、ステップの最後の状態です。 ステップが失敗した場合はどうなりますか? たとえば、製品が誤った状態になった原因の図を見たいです。
ですから、第6章で説明した焦点を回すと、実行中に外部から呼び出すことができるレポートのステップ詳細を作成する機会があれば、それは素晴らしいことだと思います。
5.他のすべてがツキュダイドを行います。
そのようなもの!
現時点では、サードパーティ製のツールを使用して機能を拡張できない、モンスターのようなシステムを開発することは理想的な選択肢ではないと思います。 , :
— ;
— , , Selenium Webdriver .

.
8. .
.
Google Drive. Yandex QA Tools Html Elements. , - . . FireFox, Chrome, Safari RemoteWebDriver, Chrome.
*.jar . - , :
1. jdk7.
2. maven project.
3. . selenium ( 2.35) TestNG!
4. pom.xml .
, . . , - . , . . - . . . , , , ?
9. .

, . …
, , , . , – – , - .
, . , - . , , . - , , .
. , . - . :
— . :
FireFox ( 21.0);
Chrome (26-30);
Internet Explorer ( 9.0.8112);
Safari (5.1.7 Windows);
Opera (12.16)
HTMLUnitDriver – ;
RemoteWebDriver c .
— iPhone Android, PhantomJS.
— TestNG. .
— Junit .
— .
, - . ( ), , .
じゃあね!