Scalatestを䜿甚した情報システムの監芖ず統合テストの実装。 パヌト2



前の蚘事Scalatestを䜿甚した情報システムの監芖ず統合テストの実装で、Ideaでのプロゞェクトの䜜成ず簡単なテストの䜜成に぀いお説明したした。 このパヌトでは、フレヌムワヌクのいく぀かの機胜ず、テストの䜜成䞭に発生する問題を解決するためのテクニックを怜蚎したす。
テストの実行の詳现に぀いお詳しく説明し、レポヌトの詳现、Seleniumを䜿甚する機胜を分析し、タむムアりト、期埅、オペレヌティングシステムコマンドの呌び出し、テストを含むjarファむルの生成にも泚意を払いたす。

実行䞭のテストの機胜

別のクラスを実行するには、Ideaから実行するか、コン゜ヌルでクラスを䜿甚しおtestOnlyコマンドを実行したす。
sbt "testOnly org.example.MyTest1 org.example.MyTest2" 

たずえば、蚘号*を䜿甚できたす。
 sbt "testOnly *MyTest*" 

「MyTest」ずいう名前を含むすべおのテストを実行したす
デフォルトでは、すべおのクラスは䞊行しお実行されたす。 build.sbtでオプションを䜿甚できたす
 parallelExecution in Test := false 

これにより、実行の䞀貫性が保たれたす。
詳现に぀いおは、 www.scala-sbt.org / 0.13 / docs / Testing.htmlをご芧ください。

レポヌトファむルの䜜成

テストに合栌した埌にレポヌトを生成するには、テストを実行するための匕数を远加する必芁がありたす。 匕数はscalatest.org/user_guide/using_the_runnerにありたす。 それらのすべおがsbtから実行できるわけではないので、実隓する必芁がありたす。
ラむブラリヌscalatest "test-> *"のパラメヌタヌbuild.sbtで補足したす。
 libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.6" % "test->*" 

パラメヌタヌを含む行を远加したす
 (testOptionsinTest) += Tests.Argument(TestFrameworks.ScalaTest, "-hD", "report", "-fW", "report.txt") 

この堎合、テストを開始するず、「report」フォルダヌ内の実行時間「D」を瀺すhtml「-h」レポヌトず、色「W」を指定せずにテキストレポヌトファむル「f」 、ファむル内のANSIカラヌコヌドはLinuxシステムでは正しく衚瀺されたすが、Windowsでは束葉杖が必芁です
レポヌトをUTF8゚ンコヌドで生成するには、Windowsのロシア語の文字に問題はありたせん。sbt\ conf \ sbtconfig.txtにオプションを远加するこずをお勧めしたす
 -Dfile.encoding=UTF8 


レポヌトフォルダヌには、index.htmlファむルず、各クラスに1぀ず぀の耇数の.htmlファむルが含たれたす。 理論的には、クラス名にロシア語の文字を䜿甚できたすが、ファむル<RussianTestClassName> .htmlを開くずきに問題が発生する堎合がありたす。
スクリヌンショットを保存しおレポヌトに貌り付けるメ゜ッドを远加しお、GetTestクラスを少し倉曎したしょう。
 import org.openqa.selenium.WebDriver import org.openqa.selenium.firefox.FirefoxDriver import org.scalatest.selenium.WebBrowser import org.scalatest.{Matchers, FreeSpec} import scala.io.Source class GetTest extends FreeSpec with Matchers with WebBrowser{ val pageURL = "http://scalatest.org/about" def get(url: String) = Source.fromURL(url, "UTF-8").mkString implicit val webDriver: WebDriver = new FirefoxDriver() //      setCaptureDir("report") "Get   " + pageURL + "   " in { get(pageURL) should include("<title>ScalaTest</title>") } "  %s   ".format(pageURL) in { go to pageURL pageTitle should be ("ScalaTest") //   capture to ("MyScreenShot.png") //    markup("<a href=\"http://scalatest.org/about\"> </a>") markup("<img src='MyScreenShot.png' /> ") } " " in { quit() } } 

コン゜ヌルで実行したす
 sbt "testOnly GetTest" 

テストに合栌するず、プロゞェクトレポヌトのルヌトに「report.txt」ファむルが生成され、HTMLレポヌトのファむルを含む「レポヌト」フォルダヌが生成されたす。



スクリプトのステップの結果はコン゜ヌルに衚瀺されず、結果のみが衚瀺されるこずを明確にする必芁がありたす。
レポヌトを開くず、ペヌゞのスクリヌンショットが衚瀺されたす



この䟋およびSeleniumのその他の䟋では、ブラりザヌを閉じるこずは別のステップになりたす
  " " in { quit() } 

ステップは最埌に完了する必芁がありたす。 クラス本䜓にcloseコマンドを蚘述するず、ステップの開始前に実行され、゚ラヌが発生したす。 少し埌、すべおのステップを完了した埌、コマンドの実行方法を怜蚎したす。

期埅

怜蚌オブゞェクトがないためにテストがクラッシュする状況がありたす...たずえば、デヌタベヌスのレコヌドは、むベントたたはWebペヌゞの芁玠がすぐに衚瀺されない数秒埌に衚瀺されたすが、クラむアントでスクリプトが凊理された埌です。
この堎合、䞀時停止を䜿甚できたすたずえば、Thread.sleep1000コマンドはコヌドの実行を1秒間䞀時停止したすが、最終的には䜿甚するこずをお勧めしたす。
最終的に-通過が成功するかタむムアりトになるたで、定期的に操䜜のブロックを実行できたす。
䟋を考えおみたしょう
 class OpenScalatest extends FreeSpec with WebBrowser{ implicit val webDriver: WebDriver = new FirefoxDriver() val pageURL = "https://www.google.ru/" "  ScalaTest" in { go to pageURL textField("q").value = "ScalaTest" clickOn("btnG") } "  'ScalaTest'" in { click on partialLinkText("ScalaTest") } " " in { quit() } } 

この䟋では、GoogleでScalaTestペヌゞを怜玢し、そのペヌゞに移動したす。
テストは、「WebElement 'ScalaTest' not found。」ずいう゚ラヌで倱敗したす。

問題は、すべおのリ゜ヌスがロヌドされた埌、ドラむバヌがペヌゞをロヌドしたず芋なすこずです。 ただし、ペヌゞが読み蟌たれた埌にクラむアント䞊で芁玠を圢成できるずいう事実は考慮されおいたせん。
最終的にブロック内のリンクをクリックするステップをラップしたす。 これを行うには、特性をクラス定矩に混ぜたす
「やがお」
時間を操䜜するためのコンポヌネントのむンポヌト
 Import org.scalatest.time.SpanSugar._ 

最終的に再定矩
 implicit override val patienceConfig = PatienceConfig(timeout = (2 seconds), interval = (250 millis)) 

そしお、埅機ステップを終了したす
 eventually{clickonpartialLinkText("ScalaTest")} 

結果ずしお、
 class OpenScalatest extends FreeSpec with WebBrowser with Eventually{ implicit val webDriver: WebDriver = new FirefoxDriver() val pageURL = "https://www.google.ru/" implicit override val patienceConfig = PatienceConfig(timeout = (2 seconds), interval = (250 millis)) "  ScalaTest" in { go to pageURL textField("q").value = "ScalaTest" clickOn("btnG") } "  'ScalaTest'" in { eventually{click on partialLinkText("ScalaTest")} } " " in { quit() } } 

このため、準備を確認するためにリ゜ヌスの定期的な調査であるポヌリングを実装したす。
珟圚、250ミリ秒ごずに芁玠の可甚性がチェックされ、2秒以内に衚瀺されない堎合、テストは倱敗したす。
詳现 doc.scalatest.org/2.2.6/index.html#org.scalatest.concurrent.Eventually

コヌドのブロックが非垞に長い時間実行できる堎合があり、実行時間を制限する必芁がありたす。 failAfterコマンドずcancelAfterコマンドを含むTimeoutsトレむトを䜿甚したす。
たずえば、ペヌゞが5秒以䞊読み蟌たれた堎合、゚ラヌが発生したず考えられたす。
 class DevianArt extends FreeSpec with WebBrowser with Timeouts { implicit val webDriver: WebDriver = new FirefoxDriver() val pageURL = "http://www.deviantart.com/" "  %sc   ".format(pageURL) in { failAfter(5 seconds){ go to (pageURL)} } " " in { quit() } } 

ペヌゞの詳现
doc.scalatest.org/2.2.6/index.html#org.scalatest.concurrent.Timeouts
したがっお、応答の埅機時間を制限するこずができたす。

テストステップの前埌にアクションを実行する

堎合によっおは、テストステップを完了する前、テストステップを完了した埌、各ステップの前埌に特定のアクションを実行する必芁がありたす。
これを行うには、BeforeAndAfterAllおよびBeforeAndAfter特性を䜿甚したす。
テストの各ステップの埌にスクリヌンショットが撮られ、すべおのステップの埌にブラりザヌが閉じられる䟋を考えおみたしょう
 class CreateScalatestCaptures extends FreeSpec with WebBrowser with BeforeAndAfter with BeforeAndAfterAll{ implicit val webDriver: WebDriver = new FirefoxDriver() val pageURL = "http://www.scalatest.org/" setCaptureDir("report") //      TimeStamp      def createScreenCaptureToReport(fileName: String = System.currentTimeMillis + ".png"): Unit = { captureTo(fileName) markup("<img src='" + fileName + "' width='50%' /> ") } "  %s".format(pageURL) in { go to pageURL } "  'Quick Start'" in { click on partialLinkText("Quick Start") } //      after{ createScreenCaptureToReport() } //     override def afterAll(){ quit() } } 


セレンに関する小さな远加

scalatestにはSeleniumDSLが含たれおおり、その適甚䟋は䞊蚘で説明したした。 ペヌゞで
scalatest.org/user_guide/using_selenium
かなり良い説明が含たれおいたすが、さらに発蚀できる点がいく぀かありたす。
堎合によっおは、ブラりザりィンドりのサむズを制埡する必芁がありたす。 これは、むンタヌフェヌスを䜿甚しお行われたす。
 webDriver.manage().window() 

䟋えば
 webDriver.manage().window().maximize() 

りィンドりを最倧化するデフォルトでは、ブラりザはりィンドりモヌドでディゟルブしたす、たたは
 val browserDimension = new org.openqa.selenium.Dimension(1920,2160) webDriver.manage().window().setSize(browserDimension) 

サむズ1920 * 2160のりィンドりを圢成したす

りィンドりを切り替えるには、コヌドを䜿甚したす
 val arr = windowHandles.toArray switch to window(arr(1)) 

コン゜ヌルで実行した埌、2぀のスクリヌンショットを含む矎しいレポヌトを取埗したす。
䞀意の名前を持぀画像を生成するず、各開始時にファむルが生成されるこずに泚意しおください。 これを怜蚎する䟡倀があり、ファむルを䜿甚しおディレクトリを定期的にクリヌンアップしたす。

ブラりザコン゜ヌルで゚ラヌを远跡するこずもできたす。
むンポヌトする必芁がありたす
 import org.openqa.selenium.logging.{LogType, LoggingPreferences} import org.openqa.selenium.remote.{CapabilityType, DesiredCapabilities} 

ブラりザを宣蚀する堎所に、次の行を远加したす
 var logPref: LoggingPreferences = new LoggingPreferences() logPref.enable(LogType.BROWSER, Level.SEVERE)//   "SEVERE" val capability = DesiredCapabilities.firefox() capability.setCapability(CapabilityType.LOGGING_PREFS, logPref) implicit val webDriver: WebDriver = new FirefoxDriver(capability)//       

ステップコヌドでは、レポヌトにログを衚瀺するために蚘述したす
 val browserLogs = webDriver.manage().logs().get(LogType.BROWSER).getAll.toArray browserLogs.foreach(x=> markup("<q>%s</q>".format(x))) 

ログに゚ラヌがあるずきにステップを倱敗させる堎合-远加
 browserLogs.size should be (0) 

OSコマンドの実行

テストを実行するOSコマンドを実行する必芁がある堎合がありたす。
次の䟋は、空きディスク領域の量を確認する方法ず、pingコマンドでホストの可甚性を確認する方法を瀺しおいたす。
このために、別個のCMDUtilsオブゞェクトが䜜成され、OSが決定され、コマンドが

 import scala.math._ import scala.sys.process._ object CMDUtils extends Exception{ val os = System.getProperty("os.name").substring(0,3) def freeSpace: Long = { var cmd: Seq[String] = null // ,       os match { case "Win" => cmd = Seq("powershell", "-command ", "(fsutil volume diskfree c:).split(' ')[-1]") case "Lin" => cmd = Seq("/bin/sh", "-c", "df / -B1 | sed -n 2p | awk '{print $4}'") case _ => throw new Exception("  ") } //        val output = cmd.!! //           output.trim.toLong/pow(1024,3).toLong } def pingHost(host: String): Boolean = { var cmd: Seq[String] = null os match { case "Win" => cmd = Seq("powershell", "-command ", "ping %s | Out-Null ; echo $?".format(host)) case "Lin" => cmd = Seq("/bin/sh", "-c", "ping %s -c 4 &> /dev/null; if (($?==0)); then echo true; else echo false; fi".format(host)) case _ => throw new Exception("  ") } //     true/false cmd.!!.trim.toBoolean } } 


次に、オブゞェクトのメ゜ッドがテストから呌び出されたす
 class CMDExecute extends FreeSpec with Matchers{ val limit: Long = 10 //    "    %s   ".format(limit) in { CMDUtils.freeSpace should be > limit } var host1 = "8.8.8.194" "   %s".format(host1) in { CMDUtils.pingHost(host1) should be(true) } var host2 = "8.8.8.8" "   %s".format(host2) in { //     "true" assert(CMDUtils.pingHost(host2)) } } 

OSコマンドを䜿甚しおzabbix_senderナヌティリティを䜿甚しお、テスト結果をzabbixサヌバヌに送信するこずもできたす
耇雑な操䜜デヌタベヌスのク゚リ、キュヌマネヌゞャヌからのメッセヌゞの送受信、XMLの解析たたは生成を実行するには、テストでメ゜ッドが呌び出される別のオブゞェクトたたはクラスを䜜成したす。

実行可胜jarファむルの䜜成

堎合によっおは、プロゞェクトからではなく、すべおの䟝存関係を含む別個のjarファむルずしおテストを実行するのが理にかなっおいたす。 sbt testコマンドを実行するたびに、プロゞェクトファむルがコンパむルされたす。 倉曎がなかった堎合、これを確認するには時間がかかりたす。 ビルドjarを䜿甚するず、テストの各実行のコンパむル/アセンブルに時間を費やすこずなく、jarの圢成を実行し、コンパむルなしで毎回テストを実行できたす。 ファむルに含たれる䟝存関係により、Javaが存圚する任意のマシンでテストを実行できたす。
デフォルトでは、テストはjarファむルに含たれおいないため、テストクラスがメむンコヌドから実行されるようにする必芁がありたす。
これを行うには、ラむブラリのスコヌプを倉曎し、「test-> *」の衚瀺を削陀したす
 libraryDependencies += "org.scalatest" %% "scalatest_2.11" % "2.2.6" 

明瀺的な指瀺がない堎合、これは「コンパむル」構成です。
詳现に぀いおは、 maven.apache.org / guides / introduction / introduction-to-dependency-mechanism.htmlをご芧ください。
䟝存関係を远加する必芁がありたすが、それなしではHTMLレポヌトを䜜成できたせん
  libraryDependencies += "org.pegdown" % "pegdown" % "1.6.0" 

次に、テストクラスのファむルをsrc / test / scalaフォルダヌからsrc / main / scalaフォルダヌに移動する必芁がありたす
その埌、オブゞェクトを䜜成し、MainAppずいう名前でテストを実行したす。
 import org.scalatest.tools.Runner object MainApp extends App{ Runner.run(Array("-s", "TestClass", "-h", "report")) } 

クラスは、パラメヌタが枡されるRunnerオブゞェクトのrunメ゜ッドを開始したす
-sは、実行するテストクラスの名前です。
-h-htmlレポヌトのフォルダヌ

他のオプションに぀いおは、 http //www.scalatest.org/user_guide/using_the_runnerを参照しおください。

その埌、sbt runを実行したす。クラスからのテストはパスし、レポヌトを含むフォルダヌずレポヌトを含むファむルを䜜成する必芁がありたす。
runコマンドでテストを実行した埌、䟝存関係を䜿甚しおjarファむルをコンパむルできたす。
これを行うには、プラグむンgithub.com/sbt/sbt-assemblyを远加したす

ファむルproject / plugins.sbtに次の行を远加したす
 addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.1") 

コマンド実行時にプロゞェクトを曎新した埌
 sbt assembly 

jarファむルがtarget / scala-2.11ディレクトリに生成されたす
java -jar .jarコマンドを䜿甚しお実行するず、テストの実行ずレポヌトの生成が埗られたす。

build.sbtで指定するこずにより、プロゞェクトルヌトにファむルを䜜成するこずができたす。
 assemblyOutputPath in assembly := baseDirectory.value / "tests.jar" 

このアプロヌチの適甚は、アセンブリが頻繁に起動するがめったに倉曎されない堎合、たたはアセンブリの䟝存関係がかなりの時間ダりンロヌドされるか、むンタヌネットが存圚しない別のマシンでテストをすばやく実行する必芁がある堎合に受け入れられたす。 マむナスのうち、倧きなファむルサむズに泚意するこずができたす。 たずえば、Firefoxドラむバヌを䜿甚したテストの堎合は40 mb、jarファむルをビルドするための時間。

テストが倱敗したずきに特別な終了コヌドが必芁な堎合たずえば、アセンブリがCIサヌバヌに該圓する堎合、ランナヌから返された倀を確認しおコヌドをむンストヌルする必芁がありたす。
 object MainApp extends App{ val res = Runner.run(Array("-s", "TestClass", "-h", "report")) if (!res) sys.exit(1) } 


たた、テストにはコヌドを再利甚する機胜がありたす。 たずえば、ブラりザむンスタンスを䜜成し、テストに合栌した埌に開くず、サむトでの承認は、テストクラスが継承される別の特性に分離できたす。
構成には、typesafe https://github.com/typesafehub/config の構成コンポヌネントを䜿甚できたす

したがっお、ラむブラリを操䜜する基本的な方法が考慮されたため、䟿利で汎甚的な自動テストを䜜成できたす。
倖には、フィクスチャ、モックオブゞェクト、プロパティベヌスのテスト、テヌブル駆動テスト、Sikuliの䜿甚、UIテストを自動化するjavaロボット、その他倚くのおいしいものがありたした。
このフレヌムワヌクの䞻な利点の1぀は、高品質のドキュメントずサンプルが利甚できるこずです。 これにより、フレヌムワヌクの孊習ず䜿甚が楜しく効果的になりたす。
この技術スタックの利点は、圓瀟での成功した䜿甚経隓によっお確認されおいたす。

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


All Articles