UIテスト:Cucumber + Selenide

パート2


Selenideを使用したCucumberでの UIテストの記述に関する記事の続き。 最初の部分では、 riskmarket.ruの煙テストの最も単純な例を分析しました 。 このパートでは、テストをレポート付きの本格的なプロジェクトにアップグレードし、スクリーンショット、カスタムConditionについて説明し、要素に注釈を付け、 PageObjectを紹介します


結果のプロジェクトは、UIテストの基盤として使用できます。


Githubプロジェクト


Youtubeテスト実行ビデオ




プロジェクト構造:




Intellij IDEAMavenおよびJunitを使用します。


ログイン 、テストを操作するためのアカウントパスワードはmail.txtに記録されます注意:自宅で始める場合、システムは1つのログイン/パスワードでログインするユーザーの1人を除外することに注意してください。 メールを変更する


pom.xmlの依存関係:


 <dependencies> <dependency> <groupId>com.codeborne</groupId> <artifactId>selenide</artifactId> <version>3.5</version> </dependency> <dependency> <groupId>info.cukes</groupId> <artifactId>cucumber-java8</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>info.cukes</groupId> <artifactId>cucumber-junit</artifactId> <version>1.2.4</version> </dependency> </dependencies> 

最初の部分と比較して、 cucumber-junitcucumber-junit -CucumberでJunitテストを実行するためのライブラリです。 少なくともTestNGには同じことがあります


ランナーパッケージを追加しました。 これにはSmokeTestクラスが含まれており 、これはmunit testコマンドによって実行されるテストとしてJunitによって解釈されます。 このクラスをさらに詳しく考えてみましょう。


 @RunWith(Cucumber.class) @CucumberOptions( plugin = {"html:target/cucumber-report/smoketest", "json:target/cucumber.json"}, features = "src/test/java/ru/riskmarket/features", glue = "ru/riskmarket/steps", tags = "@smoketest") public class SmokeTest { @BeforeClass static public void setupTimeout() { Configuration.timeout = 10000; } } 

@RunWithこのJUnitテストをCucumberで実行する責任がある注釈


@CucumberOptions CucumberOptions-ここでCucumberテストを設定します


pluginテストレポートの作成を担当します(以前はformatと呼ばれていformat )。 後のレポートについて


features - featuresへの道


glue -ステップへの道


tags - tags 、さらに個々のスクリプトにtagsを割り当てることができます。 このパラメーターは、実行されるテストを示します。


タグはコンマ区切りの行として記述されます: “@smoketest, @alltests, @special” 。 たとえば、いくつかの機能があり、 @alltests@alltestsを追加し、パラメーターtags = “@alltests”ランナーを実行して、すべてのテストを実行できます。


タグは、 Features:キーワードの前のFeatures:追加されます。スペースまたは改行でFeatures:


クラス本体自体は空のままにすることができますが、低速のインターネットでテストを実行するため、ここでSelenidタイムアウトを設定します-これをJUnitの@BeforeClass 、デフォルトの4に対して10を指定します。 また、構成では、たとえば、どのブラウザーでテストを実行するかを指定できます


 System.setProperty("webdriver.chrome.driver", "src/main/resources/chromedriver.exe"); Configuration.browser = "chrome"; 

ブラウザーを変更する場合は、 Selenium Webサイトから必要なドライバーをダウンロードし、その場所を示すことを忘れないでください。 ここで、例として、ランナーの行をコメント化したままにします。


smoketest 機能のステップは、最初の部分の機能からのアクションを繰り返しますが、少し異なって記述されています。 PageObjectを使用するようになりました


PageObjectは、テストに必要な要素の定義を含む個々のページのクラスがあり、セレクターが指定されていることを意味するパターンです。 次に、ステップロジックでは、セレクターではなく、以前に定義された要素が使用されます。 これは、プロジェクトのhtml構造が変更された場合に必要です。 変更が発生した場合、 PageObject内のセレクターのみが変更され 、どのセレクターが現在機能しており、どのセレクターが機能していないか、すべてのStepDefinitionを調べる必要はありません。


テストでは、 ru.riskmarket.pageobjectsパッケージにリストされている3つのページがあります。 ページはテストそのものではないため、 main / javaで ページ オブジェクトを( 並べ替えて)記述するのが慣例です。 各ページは、テストが対話するページに属する要素を示します。


注釈を追加する


ここで、100ページの要素、動的テーブル、他の何か、一般に複雑なプロジェクトを含む複数のページを持つ巨大なプロジェクトがあると想像してください。 この場合、このタイプの要素- 「調整テーブルの3列目の最初のセル」が表示されます 。 ステップを再利用したいという要望を考えると、何らかの方法で要素の名前を、ステップのロジックを決定するメソッドに転送する必要があります。 PageObjectの複雑な要素は、このように定義されます


 @FindBy(xpath = "") public SelenideElement firstCellAtThirdRowAtAssessmentTable; 

そして、このセルに何かを書き込むステップは次のようになります。


 And type to firstCellAtThirdRowAtAssessmentTable text: "Hello, Cucumber!" 

ご覧のとおり、ステップを明確にする利点は失われます。 ステップは次のようになります。


 And type to “First Cell At Third Row At Assessment Table” text: "Hello, Cucumber!" 

次に、 StepDefのstepメソッドを何らかの方法で一致させて、要素をステップ自体の名前と一致させる必要があります。
私の解決策は、 @NameOfElementアノテーションを追加すること@NameOfElement


注釈は分析しません。これは別のトピックです。 主なものは、それらを書くことは非常に簡単です。


その結果、注釈を追加した後、二重のジョブを取得します。特にその名前がわかっているため、要素を直接アドレス指定する代わりに、これはリフレクションと注釈によって行われます。 しかし、これは美しくて読みやすい機能の犠牲です。


その結果、要素は次のように定義されます。


 @NameOfElement("First Cell At Third Row At Assessment Table") @FindBy(xpath = "") public SelenideElement firstCellAtThirdRowAtAssessmentTable; 

そして、 StepDefで


 @And("^type to input \"([^\"]*)\" text: \"([^\"]*)\"$") public void typeToInputText(String nameOfElement, String text) { somePage.get(nameOfElement).sendKeys(text); } 

get(nameOfElement)メソッドはリフレクションを使用してページクラスのフィールドを名前で@FindBySeleniumの @FindByしてページ上の要素を返します。


get(nameOfElement)メソッドはAbstractPage.javaクラスで定義され、すべてのページに継承されます。


MyStepDefの変更について説明しましょう。


追加されたフィールド


 FirstPage firstPage = page(FirstPage.class); SecondPage secondPage = page(SecondPage.class); ThirdPage thirdPage = page(ThirdPage.class); 

page(PageObject.class)は、Selenium PageFactoryをカプセル化するpage(PageObject.class)メソッドです。 繰り返しますが、コードの大幅な削減。 これは、ページ上の要素を検索するときに@FindByを満たすために必要です。


ステップメソッドでは、プロジェクトの最初のバージョンとは異なり、Selenid $() 、名前で目的のページの要素を検索することで置き換えられます。 すべてのページに共通のステップでは、すべてのページにわたって要素が検索されます。


shouldの詳細(条件)


本質的に、Selenidによる条件のチェックは、shouldHave should/shouldBe/shoudHave/…. (メソッドは同じことをしますが、読みやすいように異なる方法で呼び出されます)、それらはassert'に類似していますが、 assertを使用する場合は、落ちるアサーションのスクリーンショットを作成するように注意する必要があります。 繰り返しになりますが、テスターが逆アセンブルする必要がある追加コードは、代わりに提供されます。 そして、 キュウリの場合にはまだ多くの問題があります。


should(Condition)が落ちると自動的にスクリーンショットが撮られ、スクリーンショットへのリンクがレポートに表示されます。 デフォルトでは、これらはビルドプロジェクトフォルダーに保存されます。


ログクリッピング:


 Element not found {By.xpath: //button[.='  ']} Expected: visible Screenshot: file:/C:/Users/vkov/Documents/GitHub/RiskMarket/complex_selenide_cucumber/build/reports/tests/1460907962193.0.png 

ご覧のように、ロギングはassertThat類推によって行われassertThat - assertThatあるべきことと実際に起こったことを示します。


ほとんどの場合、必要なConditionはすでに記述されていますassertThatを使用する前に確認してassertThat 。 極端な場合、必要なCondition不要で、スクリーンショットを撮る必要がある場合は、独自の条件を作成できます。 この簡単な例は、 CustomConditionクラスにあります。 Condition.appear実行するアクションを繰り返します。


should()についてshould() 、独自の説明を追加できます。


 somePage.get(" ").shouldBe(Condition.visible.because(" ...")) 

Cucumberの場合、このチェックが行われるステップを説明するテキストを間違いなく繰り返すので、これは不要だと思います。


要素のコレクションの場合、 should()も記述されます。 プロジェクトの例:


機能の入力:


  Then collection of " " should not be empty 

MyStepdefsで表示:


  @Then("^collection of \"([^\"]*)\" should not be empty$") public void collectionOfShouldNotBeEmpty(String collection) { ElementsCollection selenideElements = secondPage.getCollection(collection); selenideElements.shouldHave(CollectionCondition.sizeGreaterThan(0)); } 

説明は不要であり、コードからすべてが明らかです。


レポートについて話す


「SmokeTest.java」ランナークラスに戻る


 @RunWith(Cucumber.class) @CucumberOptions( plugin = {"html:target/cucumber-report/smoketest", "json:target/cucumber.json"}, features = "src/test/java/ru/riskmarket/features", glue = "ru/riskmarket/steps", tags = "@smoketest") public class SmokeTest { @BeforeClass static public void setupTimeout() { Configuration.timeout = 10000; } } 

@CucumberOptionsプラグインを指定しない場合、レポートは生成されません。


plugin = {“ html:target/cucumber-report/smoketest”}は、次の形式でレポートを作成します。



成功したステップは緑、赤でマークされます-落ちた、青緑色-実行されませんでした。 また、黄色になります-これは、ステップが定義されていないことを意味します。 赤い背景には、スクリーンショットとStackTraceの残りの部分へのリンクがあります。


これらのレポートは、読みやすく読みやすく、バグを開始するときに再現手順でコピーして貼り付けることができます。


しかし、さらに優れています。
ここから: https : //github.com/damianszczepanik/maven-cucumber-reporting


pom.xmlに追加


 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <testFailureIgnore>true</testFailureIgnore> </configuration> </plugin> <plugin> <groupId>net.masterthought</groupId> <artifactId>maven-cucumber-reporting</artifactId> <version>2.0.0</version> <executions> <execution> <id>execution</id> <phase>verify</phase> <goals> <goal>generate</goal> </goals> <configuration> <projectName>cucumber-selenide-example</projectName> <outputDirectory>target/cucumber-html-reports</outputDirectory> <cucumberOutput>target/cucumber.json</cucumberOutput> <parallelTesting>false</parallelTesting> </configuration> </execution> </executions> </plugin> </plugins> </build> 

@CucumberOptions plugin = {"json:target/cucumber.json"}指定します。 このモジュールは、.jsonレポートからレポートを収集します。


文字列<cucumberOutput>target/cucumber.json</cucumberOutput> -.jsonレポートを取得する場所を設定します


<outputDirectory>target/cucumber-html-reports</outputDirectory> -レポートを追加する場所を設定します。


モジュールはmvn clean installを介してのみ機能します。 target / cucumber-html-reportsで実行した後 feature-overview.htmlを開き次のものを取得します。










[ ステップ ]タブ(最後のスクリーンショット)で、リファクタリングのステップを分析するための推定時間。


一般的に、このモジュールはCI Jenkins向けに作成されています。 Jenkinsでこのようなレポートを取得する方法はこちらをご覧くださいhttps : //github.com/damianszczepanik/cucumber-reporting


Bamboo用に構成されていないため、この記事で説明するモジュールを使用して、レポート位置の場所をアーティファクトとして単純に示すことができます。


それだけです 明確な、落下テストではありません!


PSパラメーター化されたステップ(シナリオの概要:、例:)の使用は記事に適合していませんでし

Source: https://habr.com/ru/post/J283422/


All Articles