Java + Selenium + FlexMonkiumを䜿甚しおFlexアプリケヌションを自動化する

この投皿では、テストの自動化に関する質問がプロゞェクトで提起されたずきにやらなければならなかった私の研究に぀いお説明したす。 このプロゞェクトはWebサむトであり、クラむアント郚分はFlexで蚘述され、サヌバヌ郚分はPythonDjangoで蚘述されおいたす。



自動化のためのツヌルの遞択


始めるために、Java + Selenium + FlexMonkiumバンドルに萜ち着く前に行った最初からのパスを怜蚎しおください。 そしおこれ







自動化ツヌルずしお最初に䜿甚しようずしたのは、SfapiSelenium Flex-APIでした。 Selenium RCおよびドラむバヌJava、C、Python、Rubyがあるプログラミング蚀語ず連携しお動䜜したす。 利点のうち、これは実際に機胜する無料の゜リュヌションであるこずに泚意しおください。 欠点の-倚くのコヌドが、十分な結果ではありたせん。 アプリケヌションの動的な芁玠ではうたく機胜したせん。 ゜リュヌションをさらに怜玢する理由は、単玔な操䜜を実行する倧量のコヌドでした。



私が詊した次のFlex自動化゜フトりェアはRanorex Studioでした。 これは、盎感的なむンタヌフェヌスを備えた非垞にナヌザヌフレンドリヌな゜フトりェアパッケヌゞです。 さらに、組み蟌み機胜ずSpy゚ヌゞェントナヌザヌアクションのシヌケンスを蚘録するを䜿甚しおプログラミング蚀語を知らずにテストを迅速に䜜成し、提案されたプログラミング蚀語のいずれかに倉換しお䜜成枈みのテストを完了するこずに泚意する䟡倀がありたすサポヌトされおいる蚀語のリストは、賌入したラむセンスの皮類によっお異なりたす およびほがすべおのFlex UI芁玠ずの良奜な盞互䜜甚フォヌム䞊では、DataGrid芁玠の䞍適切な䜜業に関する苊情に遭遇したしたが、䜜業䞭に䜜業する機䌚がありたせんでした 。 欠点の1぀はラむセンスのコストが高いこずです。異なるドメむンたずえば、テストサヌバヌずメむンサヌバヌでアプリケヌションをテストする必芁がある堎合は、最初にテストでいく぀かの倉換を行っお、アプリケヌションむンタヌフェむスず正しく察話を開始する必芁がありたす。 ゜リュヌションをさらに怜玢する理由ずなったのは、ラむセンスの高コストでした。



Ranorexラむセンスの終了を埅たずに、私はフリヌ゜フトりェアの怜玢を続け、FlexMonkeyの䜿甚に関するアドバむスに出䌚いたした。 圌らのりェブサむトには、短いが理解しやすいドキュメントがあり、掻発な議論ずラむブサポヌトを行うフォヌラムもありたす。 アプリケヌション自䜓はAdobe Airで䜜成されおおり、わかりやすく䜿いやすいむンタヌフェむスを備えおいたす。







結局のずころ、FlexMonkeyは非垞に高速で䟿利で無料です。 ほがすべおのUIコンポヌネントでの動䜜を正しくサポヌトしたす少なくずもすべおが感動的で機胜したしたが、プログラミング蚀語を䜿甚しおテストを改善できないずいう欠点もありたす。 実際、コンポヌネントのプロパティのチェック、これらのプロパティの倀の比范など、基本的な機胜のみを䜿甚できたす。 ただし、たずえば、プログラミングツヌルなしでメヌルナヌザヌむンタヌフェむスにメッセヌゞを曞き蟌むこずはできたせん。 FlexMonkeyの䜜成者による次の補品は、Seleniumず連携しお動䜜し、 FlexMonkiumず呌ばれたす 。



䜜業環境のセットアップ


Flexアプリケヌションの自動化テストを開始するには、Selenium RC + FlexMonkiumず察話するようにプロゞェクトを構成し、プログラミング環境を準備する必芁がありたすたずえば、Eclipse IDEでJava蚀語を遞択したした。 さらに、すべおのアクションはステップで説明されおいたす。



1.テストを䜜成するプログラミング蚀語私の堎合はJava甚のSelenium RCおよびSelenium Client Driverをダりンロヌドしたす。



2. FlexMonkiumをダりンロヌドしたす 䟋ではバヌゞョン4.1.8を䜿甚したした。 アヌカむブには3぀のコンポヌネントが含たれたす-.swcラむブラリを含むフォルダヌ。そのうちの1぀はFlexプロゞェクトに接続する必芁がありたす。「user-extensions.js」はSeleniumサヌバヌの拡匵であり、フレックスアプリケヌション制埡コマンドを「理解」したす。 FirefoxのSelenium IDEの機胜を拡匵するテストおよび.xpiプラグむンで指定されおいたす。



3. Flash BuilderでFlexプロゞェクトを開き、ダりンロヌドしたアヌカむブの.swcラむブラリをプロゞェクトに接続したす。 アヌカむブには、最埌に同じ名前ず番号のファむルがいく぀かありたす。 番号はFlex-SDKのバヌゞョン番号を意味したす私の堎合、これは4番目のバヌゞョンです。぀たり、automation_monkey4.x.swcを接続する必芁がありたす。 その埌、プロゞェクトを再コンパむルし、出来䞊がり-Seleniumサヌバヌず察話する準備が敎いたした。



4.ここで、コマンド拡匵ファむルを䜿甚しおSeleniumサヌバヌを起動する必芁がありたす。これにより、Flexアプリケヌションの管理に固有のコマンドを「理解」できるようになりたす。 このファむルは、ダりンロヌドされたFlexMonkiumアヌカむブに含たれおおり、「user-extensions.js」ず呌ばれたす。 サヌバヌの起動時にコマンドラむンでパラメヌタヌずしお枡されたす。 これらの目的のために、次の内容の別個のbatファむルを䜜成したした。



java -jar C:\Automation\selenium-server-standalone-2.0rc2.jar -userExtensions C:\user-extensions.js







その埌、サヌバヌを安党に起動できたす。 すべおが正しく行われた堎合、bat'nikを起動した埌、次のようなりィンドりが画面にハングアップしたす。







したがっお、テスト察象のアプリケヌションはテスト自動化ツヌルず察話する準備ができおおり、Selenium-RCが起動され、フレックスコンポヌネント管理コマンドを理解したす。



最初のテストを䜜成する


テストを䜜成するための蚀語ずしお、JUnitラむブラリヌずずもにEclipse開発環境でJavaを遞択したした。 この組み合わせでは、テストは正垞に機胜したしたが、各テストの埌、JUnitはブラりザヌを再起動したした。これは、私のテストの倚くが以前のテストの継続であり、アプリケヌションの状態をリセットするのが適切ではないため、私にはお勧めできたせんでした。 いく぀かのフォヌラム怜玢の埌、この動䜜を無効にするこずはできず、JUnitの䜿甚を攟棄しなければならなかったこずを読みたした。 レポヌトでは、倱敗したテスト、これが発生したステップ、および発生した゚ラヌの数のみを知る必芁がありたした。 これらの目的のために、この情報をコン゜ヌルに衚瀺する特別な関数を䜜成したした。 テストが倱敗するず呌び出されテストが倱敗するずタむムアりトが発生したす、Javaは䟋倖をスロヌしたす。 その結果、次のコヌドが埗られたした。



 import java.awt.event.KeyEvent; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import com.thoughtworks.selenium.DefaultSelenium; import com.thoughtworks.selenium.HttpCommandProcessor; import com.thoughtworks.selenium.Selenium; public class TestRunner { private Selenium selenium; private HttpCommandProcessor proc; private int errorsFound; //        DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_ss"); Date date = new Date(); String msg_text = dateFormat.format(date); public static void main(String[] args) { TestRunner tr= new TestRunner(); tr.errorsFound = 0; try{ tr.seleniumStart(); //---- ---- tr.goMail(); tr.postSend(); tr.outBoxVerifyMessage(); }catch(Exception ex) {} } //Starting selenium server public void seleniumStart() throws InterruptedException { proc = new HttpCommandProcessor("localhost", 4444, "*firefox3 c:\\Program Files\\MozillaFirefox3.6\\firefox.exe", "http://q/"); selenium = new DefaultSelenium(proc); selenium.start(); Thread.sleep(5000); selenium.open("/site_media/"); } //Shutting down selenium server public void seleniumStop() { if (selenium != null) { selenium.stop(); selenium = null; } System.out.println("\r\nTesting compleated. Errors found: "+errorsFound); } //Error reporter public void printError(String test, String step) { errorsFound ++; System.out.println("\r\nError in Test: '"+test+"' on step: '"+step+"'"); } //Step runner public void testExec(String testName, String step, String cmd, String locator, int time) throws Exception { for (int t = 0;; t++) { if (t >= time) printError(testName, "Step "+step); try { if (proc.getBoolean(cmd, new String[] {locator})) break; } catch (Exception e) { } Thread.sleep(500); } } //----------------------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------------- //    public void goMail() throws Exception { String test = "goMail"; //Step 1.    testExec(test, "1", "isFlexMonkey", "", 60); //Step 2.    "" testExec(test, "2", "isFlexMonkey", "<UIEvent command=\"Select\" value=\"tabBar\"><arg value=\"\"/> </UIEvent>", 60); } //----------------------------------------------------------------------------------- //   public void postSend() throws Exception { String test = "postSend"; //Step 3.    "" testExec(test, "3", "isFlexMonkey", "<UIEvent command=\"Select\" value=\"buttonBarMail\"><arg value=\"\"/></UIEvent>", 60); //Step 4.    testExec(test, "4", "isFlexMonkey", "<UIEvent command=\"Open\" value=\"userDataProvider\"><arg value=\"null\"/></UIEvent>", 60); //Step 5.     testExec(test, "5", "isFlexMonkey", "<UIEvent command=\"Select\" value=\"userDataProvider\"><arg value=\" \"/></UIEvent>", 60); //Step 6.    "" testExec(test, "6", "isFlexMonkey", "<UIEvent command=\"SelectText\" value=\"subject\"><arg value=\"0\"/><arg value=\"0\"/></UIEvent>", 60); //Step 7.    testExec(test, "7", "isFlexMonkey", "<UIEvent command=\"Input\" value=\"subject\"><arg value=\"Hello, "+msg_text+"\"/></UIEvent>", 60); //Step 8.     ( ) testExec(test, "8", "isFlexMonkey", "<UIEvent command=\"ChangeFocus\" value=\"subject\"/>", 60); //Step 9.    testExec(test, "9", "isFlexMonkey", "<UIEvent command=\"Input\" value=\"message\"><arg value=\"Test of text message " +msg_text+"\"/></UIEvent>", 60); //Step 10.    testExec(test, "10", "isFlexMonkey", "<UIEvent command=\"Click\" value=\"\"/>", 60); } //----------------------------------------------------------------------------------------------- //     public void outBoxVerifyMessage() throws Exception { String test = "outBoxVerifyMessage"; //Step 1.    testExec(test, "1", "isFlexMonkey", "<UIEvent command=\"Select\" value=\"buttonBarMail\"><arg value=\"\"/></UIEvent>", 60); //Step 2.   testExec(test, "2", "isFlexMonkey", "<VerifyProperty value=\"subject\" propertyString=\"text\" expectedValue=\"Hello, "+msg_text+"\"/>", 10); //Step 3.   testExec(test, "3", "isFlexMonkey", "<VerifyProperty value=\"message\" propertyString=\"text\" expectedValue=\"Test of text message " +msg_text+"\"/>", 10); //Step 4.   testExec(test, "4", "isFlexMonkey", "<VerifyProperty value=\"fullName\" propertyString=\"text\" expectedValue=\" \"/>", 10); } }
      
      







この䟋では、アプリケヌションの内郚メヌルによるメヌル送信がテストされ、送信メヌル間の衚瀺が確認されたす。



そしお今、より詳现に。 seleniumStartおよびseleniumStop関数は、セッションを開始および終了したす。 最初の関数は、コマンドをサヌバヌに送信するSeleniumクラスのむンスタンスを初期化したす。 ホストおよびポヌトSeleniumサヌバヌが実行されおいる、ブラりザヌテストが実行される、およびURLテストされたアプリケヌションが䜿甚可胜などのパラメヌタヌがそこに転送されたす。



次はprintError関数で、テスト名ずステップ番号をパラメヌタヌずしお受け取り、コン゜ヌルに衚瀺したす。 この関数は、テストのいずれかのステップでタむムアりトになったずきに呌び出されたす。



各ステップで繰り返しコヌドのブロックを蚘述しないために、「testExec」ずいう別の関数に移動したした。 そのパラメヌタヌは、実行されるステップの名前ず番号タむムアりト埌に「printError」に送信されたす、サヌバヌのコマンド、「到達」しようずしおいるアプリケヌション内の芁玠ぞのパスロケヌタヌ、およびタむムアりトです。 䞊蚘の䟋のアプリケヌションパスには、「VerifyProperty」ず「UIEvent」の2぀のタむプがありたす。 前者は任意の芁玠の属性倀を比范するために䜿甚され、埌者は指定された芁玠に察しおアクションを実行するために䜿甚されたす。たずえば、ボタンをクリックしたす。 アプリケヌションのUI芁玠は、その名前たたはIDだけでなく、そのプロパティのいく぀かの組み合わせによっおも指定できたす。これらのプロパティは、「arg」タグでさらに瀺されたす。 より詳现なドキュメントは、 Gorilla Logicの Webサむトで入手できたす。



ロケヌタヌを手動で蚘述しないように、FlexMonkeyを䜿甚しお䞀連の手順を曞き留め、テストをxmlファむルに゚クスポヌトしお、Javaコヌドに挿入したした。 結果はこの結果です



 <FlexMonkey> <TestSuite name="NewTestSuite" description="" ignore="false"> <TestCase name="" description="null" ignore="false"> <Test name=" " description="null" defaultThinkTime="250" ignore="false"> <UIEvent command="Select" value="tabBar" prop="automationName" delay="1000" attempts="10"> <arg value=""/> </UIEvent> <Pause duration="10000"/> <UIEvent command="Select" value="buttonBarMail" prop="automationName" delay="1000" attempts="10"> <arg value=""/> </UIEvent> <Pause duration="1000"/> <UIEvent command="Open" value="userDataProvider" prop="automationName" delay="1000" attempts="10"> <arg value="null"/> </UIEvent> <UIEvent command="Select" value="userDataProvider" prop="automationName" delay="1000" attempts="10"> <arg value=" "/> </UIEvent> ...
      
      







たたは、Selenium IDEに加えおflexmonkium.xpiプラグむンをむンストヌルし、Firefoxブラりザヌから盎接テストを蚘録できたす。



ただし、いずれの堎合でも、特にアプリケヌションコンポヌネントに動的に生成されたIDがある堎合、これら2぀の方法は100正確なテストパフォヌマンスを保蚌したせん。 この堎合、必芁なコンポヌネントに明確に固有の匕数を手動で远加する必芁がありたす。 コンポヌネントのプロパティは、FlexMonkeyたたはFlexMonkiumコン゜ヌルで衚瀺できたす。







結果


珟時点では、ほずんどの回垰テストはプロゞェクトで自動化されおいたす。 数は350以䞊で、実行時間は玄3〜4時間です。



蚘事の長さを膚らたせた䟋で、このような倧きなコヌドをおaびしたす。



All Articles