Selenium自動化測試框架研究
1. 介紹
Selenium這個單詞的字面意思是"硒",Selenium的官方網站是http://www.seleniumhq.org./
2. 編譯Selenium
可以從http://selenium.googlecode.com/git/取得Selenium項目的全部源代碼。
git clone http://selenium.googlecode.com/git/ selenium
在terminal下進入selenium目錄,輸入,
./go
或者,
./go clean release
等待編譯完成。
我在編譯過程出現依賴性錯誤,需要libibus-dev包。
3. Selenium IDE
Selenium IDE是一個Firefox下的插件,可以使用Firefox直接從selenium的網站上安裝。
Selenium IDE是一個簡單的Selenium的腳本錄製、編輯和驗證工具,可以用於測試用例的錄製,並且可以把selenium的測試腳本轉換成其它的語言,如:java、python等。
4. Selenium Remote Control
Selenium Remote Control是測試服務,可以使用selenium client把測試任務指派給selenium rc,讓其執行。
通常情況下都是使用selenium rc + selenium client + selenium ide的模式來完成測試任務。
5. Selenium的編譯環境
5.1. 概述
Selenium編譯是從目錄下的go(for linux)/go.bat(for windows)這兩個文件開始的。 go文件的內容如下:
Toggle line numbers 1#!/bin/bash
3# we want jruby-complete to take care of all things ruby
4unset GEM_HOME
5unset GEM_PATH
7JAVA_OPTS="-client"
9java $JAVA_OPTS -Xmx2048m -XX:MaxPermSize=1024m -XX:ReservedCodeCacheSize=256m -jar third_party/jruby/jruby-complete.jar -X-C -S rake $*
go.bat的大致相同。
Rakefile是Rake構建工程使用的工程文件,相當於Makefile,Rakefile的語法是基於ruby的。
5.2. Rakefile
5.2.1. 介紹
Selenium使用Rake作爲構建環境,rake是一個基於ruby語言的與makefile相似的跨平臺的多任務的構建系統,其官方網站是http://rake.rubyforge.org/。
Rake構建系統的構建文件是Rakefile,到selenium項目的根目錄下,可以找到selenium的Rakefile文件。Rakefile的語法基礎是ruby,可以從rake的官方網站上找到具體的語法說明及例程。
5.2.2. Selenium的Rakefile
5.2.2.1. 導入crazyfun依賴
Toggle line numbers 1# The CrazyFun build grammar. There's no magic here, just ruby
2require'rake-tasks/crazy_fun'
3require'rake-tasks/crazy_fun/mappings/android'
4require'rake-tasks/crazy_fun/mappings/export'
5require'rake-tasks/crazy_fun/mappings/folder'
6require'rake-tasks/crazy_fun/mappings/gcc'
7require'rake-tasks/crazy_fun/mappings/java'
8require'rake-tasks/crazy_fun/mappings/javascript'
9require'rake-tasks/crazy_fun/mappings/mozilla'
10require'rake-tasks/crazy_fun/mappings/python'
11require'rake-tasks/crazy_fun/mappings/rake'
12require'rake-tasks/crazy_fun/mappings/rename'
13require'rake-tasks/crazy_fun/mappings/ruby'
14require'rake-tasks/crazy_fun/mappings/visualstudio'
5.2.2.2. 導入其它的依賴
Toggle line numbers 1# The original build rules
2require'rake-tasks/task-gen'
3require'rake-tasks/checks'
4require'rake-tasks/dotnet'
5require'rake-tasks/zip'
6require'rake-tasks/c'
7require'rake-tasks/java'
8require'rake-tasks/iphone'
9require'rake-tasks/selenium'
10require'rake-tasks/se-ide'
11require'rake-tasks/ie_code_generator'
12require'rake-tasks/ci'
14require'rake-tasks/gecko_sdks'
5.2.2.3. 使用crazyfun
Toggle line numbers 1# The build system used by webdriver is layered on top of rake, and we call it
2# "crazy fun" for no readily apparent reason.
4# First off, create a new CrazyFun object.
5crazy_fun = CrazyFun.new
7# Secondly, we add the handlers, which are responsible for turning a build
8# rule into a (series of) rake tasks. For example if we're looking at a file
9# in subdirectory "subdir" contains the line:
10#
11# java_library(:name => "example", :srcs => ["foo.java"])
12#
13# we would generate a rake target of "//subdir:example" which would generate
14# a Java JAR at "build/subdir/example.jar".
15#
16# If crazy fun doesn't know how to handle a particular output type ("java_library"
17# in the example above) then it will throw an exception, stopping the build
18AndroidMappings.new.add_all(crazy_fun)
19ExportMappings.new.add_all(crazy_fun)
20FolderMappings.new.add_all(crazy_fun)
21GccMappings.new.add_all(crazy_fun)
22JavaMappings.new.add_all(crazy_fun)
23JavascriptMappings.new.add_all(crazy_fun)
24MozillaMappings.new.add_all(crazy_fun)
25PythonMappings.new.add_all(crazy_fun)
26RakeMappings.new.add_all(crazy_fun)
27RenameMappings.new.add_all(crazy_fun)
28RubyMappings.new.add_all(crazy_fun)
29VisualStudioMappings.new.add_all(crazy_fun)
這裏可以看到rakefile通過crazyfun實現了對各種編譯環境的支持,如:Android、Java、Gcc及VS等。
5.2.2.4. 創建crazyfun的任務
Toggle line numbers 1# Finally, find every file named "build.desc" in the project, and generate
2# rake tasks from them. These tasks are normal rake tasks, and can be invoked
3# from rake.
4crazy_fun.create_tasks(Dir["**/build.desc"])
這裏在工程的所有子目錄中查找build.desc文件,並根據build.desc創建rake中的任務。
5.3. CrazyFunBuild
5.3.1. 介紹
關於crazyfun的介紹可以直接訪問,https://code.google.com/p/selenium/wiki/CrazyFunBuild。
如果需要修改或是擴展Selenium中的包或庫,就要修改對應的包或庫的build.desc文件,把增加的源代碼和路徑顯式的或隱式的添加到對應的包/庫中。
5.3.2. CrazyFun的簡單說明
其實在rakefile的crazyfun那一段中也有一個簡單的Java的例子,如下:
Toggle line numbers 1java_library(name="example",
2resources=["example.java"],
3deps=[":base"])
上面這個build.desc的說明:
用Java編譯,生成一個名爲example.jar的包;
編譯的源文件是當前目錄下的example.java
example項目編譯依賴於base.jar
5.3.3. 在Selenium進行Java二次開發
5.3.3.1. 創建Java工程
根據Selenium的目錄結構來看,可以使用Eclipse或其它的IDE創建Java工程,工程創建完成後,如果需要在Rakefile中統一編譯,則需要在對應的源代碼目錄中增加build.desc。
下面代碼是{$SeleniumHome}/java/server/src/org/openqa/selenium/server目錄下的build.desc文件,
Toggle line numbers 1java_binary(name = "server",
2main_class = "org.openqa.selenium.server.SeleniumServer",
3deps = [
4":base",
5":server_resources",
6"//java/client/src/org/openqa/selenium:client-combined",
7"//third_party/java/opera-driver",
8 ])
10# Light version of the server for drivers that don't need to depend on all other drivers.
11# We need at least one source file in here to make this build the JAR
12# TODO(simon): Only resources should be fine
13java_binary(name = "server_lite",
14main_class = "org.openqa.selenium.server.SeleniumServer",
15deps = [
16":base",
17":server_resources",
18 ])
20java_library(name = "server_resources",
21resources = [
22"customProfileDirCUSTFF",
23"customProfileDirCUSTFFCHROME",
24"hudsuckr",
25"konqueror",
26"opera",
27"sslSupport",
28"VERSION.txt",
29 ],
30deps = [
31"//javascript/selenium-core"
32 ])
34java_library(name = "logging",
35srcs = [
36"RemoteControlConfiguration.java",
37"SslCertificateGenerator.java",
38 ],
39deps = [
40"//java/client/src/org/openqa/selenium/remote:common",
41"//java/server/src/org/openqa/jetty",
42"//java/client/src/org/openqa/selenium/logging:api",
43"//java/client/src/org/openqa/selenium/logging:logging",
44"//java/server/src/org/openqa/selenium/remote/server/log",
45 ])
47java_library(name = "base",
48srcs = [
49"**/*.java",
50 ],
51deps = [
52":logging",
53"//java/client/src/org/openqa/selenium:codecs",
54"//java/client/src/org/openqa/selenium:selenium-api",
55"//java/client/src/org/openqa/selenium/browserlaunchers:launcher-utils",
56"//java/client/src/org/openqa/selenium/net",
57"//java/client/src/org/openqa/selenium/support",
58"//java/server/src/cybervillains",
59"//java/server/src/org/openqa/selenium/remote/server",
60"//java/server/src/org/openqa/jetty",
61"//third_party/java/servlet-api"
62 ])
從上面代碼可以看出,在srcs中既可以使用完整的路徑,也可以使用通配符*.java。
下面單獨以"server"這個task爲例進行說明:
Toggle line numbers 1java_binary(name="server",
2main_class="org.openqa.selenium.server.SeleniumServer",
3deps=[
4":base",
5":server_resources",
6"//java/client/src/org/openqa/selenium:client_combined",
7"//third_party/java/opera-driver"
8])
說明:
java_binary說明這個task是生成一個可以執行的jar包,在生成的MANIFEST.MF文件裏有Main-Class;
name是指出生成的jar包的名字;
main_class指出這個可執行的jar包的入口點是SeleniumServer,這會寫入MANIFEST.MF文件,如:"Main-Class:org.openqa.selenium.server.SeleniumServer";
":base"是本地的依賴關係,"//third_party/java/opera-driver"這樣的寫法是指出非本地的依賴包。
5.3.4. 在Selenium中進行C or C++ 二次開發
Selenium中的C/C++模塊由cpp目錄下的build.desc在管理,按照Selenium的目錄結構,由C或C++開發的庫或應用程序工程都放在cpp目錄,並且在build.desc中添加對應的task。
下面具體分析build.desc的內容。
5.3.4.1. GCC編譯
Toggle line numbers 1gcc_library(name = "noblur",
2srcs = [ "linux-specific/*.c" ],
3args = "-I/usr/include",
4arch = "i386")
6gcc_library(name = "noblur64",
7srcs = [ "linux-specific/*.c" ],
8args = "-I/usr/include",
9arch = "amd64")
說明:
"gcc_library"指出輸出一個.a或.so的庫文件;
"srcs"需要編譯的.c文件的路徑;
"args"是一些需要的編譯參數,如:"-I"、"-L"等;
"arch"是編譯器的架構,i386是32位,amd64是64位。
5.3.4.2. VS編譯
Toggle line numbers 1visualc_library(name = "firefox_dll",
2platform = "Win32",
3project = "webdriver-firefox/webdriver-firefox.vcxproj",
4file_deps = "third_party/gecko-2/win32",
5out = "Win32/Release/webdriver-firefox.dll"
6)
7visualc_release(name = "ie_win32_exe",
8deps = [
9":atoms",
10":ie_result_type_cpp",
11":sizzle"
12 ],
13platform = "Win32",
14project = "IEDriverServer/IEDriverServer.vcxproj",
15desc = "InternetExplorerDriver standalone server for 32-bit IE",
16out = "Win32/Release/IEDriverServer.exe"
17)
說明:
"visualc_library"是輸出一個windows操作系統下的DLL庫文件;
"visualc_release"是輸出一個windows操作系統下的可執行文件;
"platform"如果是"win32",則輸出32位版本,如果是"x64",則輸出64位的版本;
"project"是指vs的工程文件的路徑;
"deps"是庫依賴;
6. Selenium工程的調試(for linux)
6.1. 調試環境的準備
從Selenium的工程目錄來看,Selenium中的Java部件可以使用Eclipse或Intellij IDEA打開。
如果需要調試C/C++的代碼需要在windows操作系統下裝有Visual Studio 10以上版本或linux操作系統下gcc + gdb支持。
6.2. Java代碼的調試
6.2.1. Eclipse導入Selenium
在eclipse的menu下的"file">>"import"打開import對話框,
選擇"Existing Projects into Workspace",
選擇selenium工程的頂級目錄,
在"Projects"中選擇要導入的工程,除了"android"以外的工程,"client"、"server"、"selenium-common"、"third-party"全部都要導入。
6.2.2. 用debug模式啓動Selenium Server
打開"selenium/java/server/src/org/openqa/selenium/server"目錄下的"build.desc"文件,找到如下,
Toggle line numbers 1java_binary(name = "server",
2main_class = "org.openqa.selenium.server.SeleniumServer",
3deps = [
4":base",
5":server_resources",
6"//java/client/src/org/openqa/selenium:client-combined",
7"//third_party/java/opera-driver",
8 ])
根據main_class中所指出的,打開SeleniumServer.java文件,從工具欄上選擇"Debug As">>"Java Application",如果沒有錯誤,服務器就會正常啓動並監聽0.0.0.0:4444地址。
6.2.3. 訪問測試服務器
使用selenium簡單錄製一個testcase,把這個case轉爲python代碼,如下,
Toggle line numbers 1fromseleniumimportselenium
2importunittest, time, re
4classtestng(unittest.TestCase):
5defsetUp(self):
6self.verificationErrors = []
7self.selenium = selenium("localhost", 4444, "*chrome", "http://www.baidu.com/")
8self.selenium.start()
10deftest_testng(self):
11sel = self.selenium
12sel.open("/")
13sel.type("id=kw", "testng")
14sel.click("id=su")
15sel.wait_for_page_to_load("30000")
17deftearDown(self):
18self.selenium.stop()
19self.assertEqual([], self.verificationErrors)
21if__name__ == "__main__":
22unittest.main()
上述內容保存爲test.py文件放到,selenium工程的py目錄下,一種方式是在console裏輸入,
python test.py
另一種方式是用sublimetext打開test.py,快捷鍵Ctrl+B運行。
運行測試代碼後,可以在eclipse下的console窗口看到server運行輸出的log及其它信息。
6.3. C/C++代碼的調試
分析gcc.rb文件後可知,linux版本沒有啓用調試選項,最終輸出的代碼使用了"-Os"優化選項,因此最終輸出的so文件中不包含符號鏈接,可以通過兩種方式解決C/C++代碼的調試,-是在gcc.rb中啓用"-g -DDBUG=1",打開調試,生成debug版本的so文件;另一個方法是在windows下用VS進行調試。
在Eclipse中搜索關鍵字"native",可以發現C++的工程生成的DLL或是SO文件都在client中調用,與Server無關。
6.3.1. 在Visual Studio 12中打開selenium的webdriver工程
在selenium的最上層目錄下,找到webdriver.sln文件,雙擊,讓visual studio打開這個文件(假設已經安裝了Visual Studio 10以上版本),
如果打開沒有發生錯誤,就可以看到如下,
過濾一下,如下圖所示,