Selenium自动化测试框架研究

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的测试脚本转换成其它的语言,如:javapython等。

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

  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的大致相同。

RakefileRake构建工程使用的工程文件,相当于MakefileRakefile的语法是基于ruby的。

5.2. Rakefile

5.2.1. 介绍

Selenium使用Rake作为构建环境,rake是一个基于ruby语言的与makefile相似的跨平台的多任务的构建系统,其官方网站是http://rake.rubyforge.org/

Rake构建系统的构建文件是Rakefile,到selenium项目的根目录下,可以找到seleniumRakefile文件。Rakefile的语法基础是ruby,可以从rake的官方网站上找到具体的语法说明及例程。

5.2.2. SeleniumRakefile

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'

 13

 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.

  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实现了对各种编译环境的支持,如:AndroidJavaGccVS等。

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的简单说明

其实在rakefilecrazyfun那一段中也有一个简单的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  ])

  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"这样的写法是指出非本地的依赖包。

5.3.4. Selenium中进行C or C++ 二次开发

Selenium中的C/C++模块由cpp目录下的build.desc在管理,按照Selenium的目录结构,由CC++开发的库或应用程序工程都放在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")

  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"是编译器的架构,i38632位,amd6464位。

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部件可以使用EclipseIntellij IDEA打开。

如果需要调试C/C++的代码需要在windows操作系统下装有Visual Studio 10以上版本或linux操作系统下gcc + gdb支持。

6.2. Java代码的调试

6.2.1. Eclipse导入Selenium

eclipsemenu下的"file">>"import"打开import对话框,

import_001.jpg

选择"Existing Projects into Workspace"

import_003.jpg

选择selenium工程的顶级目录,

import_002.jpg

"Projects"中选择要导入的工程,除了"android"以外的工程,"client""server""selenium-common""third-party"全部都要导入。

eclipse_001.jpg

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

  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及其它信息。

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中打开seleniumwebdriver工程

selenium的最上层目录下,找到webdriver.sln文件,双击,让visual studio打开这个文件(假设已经安装了Visual Studio 10以上版本)

webdriver_sln.jpg

如果打开没有发生错误,就可以看到如下,

webdriver_vs2012_001.jpg

过滤一下,如下图所示,

webdriver_vs2012_002.jpg



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章