Selenium这个单词的字面意思是"硒",Selenium的官方网站是http://www.seleniumhq.org./
可以从http://selenium.googlecode.com/git/取得Selenium项目的全部源代码。
git clone http://selenium.googlecode.com/git/ selenium
在terminal下进入selenium目录,输入,
./go
或者,
./go clean release
等待编译完成。
我在编译过程出现依赖性错误,需要libibus-dev包。
Selenium IDE是一个Firefox下的插件,可以使用Firefox直接从selenium的网站上安装。
Selenium IDE是一个简单的Selenium的脚本录制、编辑和验证工具,可以用于测试用例的录制,并且可以把selenium的测试脚本转换成其它的语言,如:java、python等。
Selenium Remote Control是测试服务,可以使用selenium client把测试任务指派给selenium rc,让其执行。
通常情况下都是使用selenium rc + selenium client + selenium ide的模式来完成测试任务。
Selenium编译是从目录下的go(for linux)/go.bat(for windows)这两个文件开始的。 go文件的内容如下:
Toggle line numbers 1#!/bin/bash
2
3# we want jruby-complete to take care of all things ruby
4unset GEM_HOME
5unset GEM_PATH
6
7JAVA_OPTS="-client"
8
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的。
Selenium使用Rake作为构建环境,rake是一个基于ruby语言的与makefile相似的跨平台的多任务的构建系统,其官方网站是http://rake.rubyforge.org/。
Rake构建系统的构建文件是Rakefile,到selenium项目的根目录下,可以找到selenium的Rakefile文件。Rakefile的语法基础是ruby,可以从rake的官方网站上找到具体的语法说明及例程。
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'
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'
13
14require'rake-tasks/gecko_sdks'
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.
3
4# First off, create a new CrazyFun object.
5crazy_fun = CrazyFun.new
6
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等。
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中的任务。
关于crazyfun的介绍可以直接访问,https://code.google.com/p/selenium/wiki/CrazyFunBuild。
如果需要修改或是扩展Selenium中的包或库,就要修改对应的包或库的build.desc文件,把增加的源代码和路径显式的或隐式的添加到对应的包/库中。
其实在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
根据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 ])
9
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 ])
19
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 ])
33
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 ])
46
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"这样的写法是指出非本地的依赖包。
Selenium中的C/C++模块由cpp目录下的build.desc在管理,按照Selenium的目录结构,由C或C++开发的库或应用程序工程都放在cpp目录,并且在build.desc中添加对应的task。
下面具体分析build.desc的内容。
Toggle line numbers 1gcc_library(name = "noblur",
2srcs = [ "linux-specific/*.c" ],
3args = "-I/usr/include",
4arch = "i386")
5
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位。
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"是库依赖;
从Selenium的工程目录来看,Selenium中的Java部件可以使用Eclipse或Intellij IDEA打开。
如果需要调试C/C++的代码需要在windows操作系统下装有Visual Studio 10以上版本或linux操作系统下gcc + gdb支持。
在eclipse的menu下的"file">>"import"打开import对话框,
选择"Existing Projects into Workspace",
选择selenium工程的顶级目录,
在"Projects"中选择要导入的工程,除了"android"以外的工程,"client"、"server"、"selenium-common"、"third-party"全部都要导入。
打开"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地址。
使用selenium简单录制一个testcase,把这个case转为python代码,如下,
Toggle line numbers 1fromseleniumimportselenium
2importunittest, time, re
3
4classtestng(unittest.TestCase):
5defsetUp(self):
6self.verificationErrors = []
7self.selenium = selenium("localhost", 4444, "*chrome", "http://www.baidu.com/")
8self.selenium.start()
9
10deftest_testng(self):
11sel = self.selenium
12sel.open("/")
13sel.type("id=kw", "testng")
14sel.click("id=su")
15sel.wait_for_page_to_load("30000")
16
17deftearDown(self):
18self.selenium.stop()
19self.assertEqual([], self.verificationErrors)
20
21if__name__ == "__main__":
22unittest.main()
上述内容保存为test.py文件放到,selenium工程的py目录下,一种方式是在console里输入,
python test.py
另一种方式是用sublimetext打开test.py,快捷键Ctrl+B运行。
运行测试代码后,可以在eclipse下的console窗口看到server运行输出的log及其它信息。
分析gcc.rb文件后可知,linux版本没有启用调试选项,最终输出的代码使用了"-Os"优化选项,因此最终输出的so文件中不包含符号链接,可以通过两种方式解决C/C++代码的调试,-是在gcc.rb中启用"-g -DDBUG=1",打开调试,生成debug版本的so文件;另一个方法是在windows下用VS进行调试。
在Eclipse中搜索关键字"native",可以发现C++的工程生成的DLL或是SO文件都在client中调用,与Server无关。
在selenium的最上层目录下,找到webdriver.sln文件,双击,让visual studio打开这个文件(假设已经安装了Visual Studio 10以上版本),
如果打开没有发生错误,就可以看到如下,
过滤一下,如下图所示,