array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 自动化测试模型 Selenium IDE Selenium Gird2 - 爱码网

1.线性测试

  每个测试脚本相对独立,且不产生其他依赖与调用,其实就是单纯的来模拟用户完整的

  操作场景。前一篇所写的测试脚本就属于线性测试。

 优点:每个脚本完整且独立

 缺点:测试用例的开发与维护成本高

2.模块化驱动测试

 把重复的操作独立成公共模块,用例执行过程中需要用到这一模块操作时则被调用。

 优点:提高了开发效率,简化了维护的复杂性,解决了脚本的重复问题。

 缺点:无法解决测试数据不同的问题。

3.数据驱动测试

 数据的改变从而驱动自动化测试的执行,最终引起测试结果的改变,直白点就是数据的参数化,

 因输入数据的不同从而引起输出结果的不同。实现数据与脚本分离。

 优点:增强脚本的复用性

4.关键字驱动测试

通过关键字的改变引起测试结果的改变。

工具:QTP,RIDE,Selenium IDE

5.模块化驱动测试实例

以登录126邮箱为例     文件名(public.py)

class login():

 #将登录步骤封装到login()函数中

    def user_login(self,driver):

        driver.find_element_by_id("idInput").clear()

        driver.find_element_by_id("idInput").send_keys("username")

        driver.find_element_by_id("pwdInput").clear()

        driver.find_element_by_id("pwdInput").send_keys("password")

        driver.find_element_by_id("loginBtn").click()

#将退出操作封装到logout()函数中

    def logput(self,driver):

        driver.find_element_by_link_text("退出").click()

        driver.quit()

 

from selenium import webdriver 

from public import login

driver = webdriver.Firefox()

driver.implicitly_wait(10)

driver.get("http://www.126.com")

login().user_login(driver)         #调用登录模块

。。。。收信,写信,删除等操作

login().user_logout(driver)     #调用退出模块

当函数被独立到单独的脚本文件中时做了一点调整,主要为函数增加了浏览器驱动的入参。

因为函数实现的操作需要通过浏览器驱动driver,driver需要通过具体调用的用例给定。

 6.数据驱动测试实例

以登录126邮箱为例     文件名(public.py)

class login():

 #将登录步骤封装到login()函数中,修改接口需要驱动,用户名和密码

    def user_login(self,driver,username,password):

        driver.find_element_by_id("idInput").clear()

        driver.find_element_by_id("idInput").send_keys("username")

        driver.find_element_by_id("pwdInput").clear()

        driver.find_element_by_id("pwdInput").send_keys("123456")

        driver.find_element_by_id("loginBtn").click()

#将退出操作封装到logout()函数中

    def logput(self,driver):

        driver.find_element_by_link_text("退出").click()

        driver.quit()

 

from selenium import webdriver 

from public import login

class loginTest():

    def _init_(self):           #在_init_()中初始化浏览器驱动.等待超时长和URL等

        self.driver = webdriver.Firefox()

        self.driver.implicitly_wait(10)

        self.driver.get("http://www.126.com")

   #admin 用户登录

def test_admin_login(self):

    username = 'admin'

    password = '123'

    login().user_login(self,driver,username,password)  #调用login()类的user_login()方法

    self.driver.quit()

 

   #guest 用户登录

 

def test_guest_login(self):

 

    username = 'guest'

 

    password = '321'

 

    login().user_login(self,driver,username,password)

 

    self.driver.quit()

 

loginTest().test_admin_login()

loginTest().test_guest_login()

7.参数化搜索关键字

以数组的方式对搜索的关键字进行参数化

首先创建一个数组search_text用来存放搜索关键字,通过for循环来遍历数组。

from selenium import webdriver 

search_text = ['python','中文','text'] 

for text in search_text:

    driver = webdriver.Firefox()

 

    driver.implicitly_wait(10)

 

    driver.get("https://www.baidu.com")

 

    driver.find_element_by_id('kw').send_keys(text)

    driver.find_element_by_id('su').click()

    driver.quit()

 8.读取txt文件

python 读取txt文件的几种方式

read():读取整个文件

readline():读取一行数据

readlines():读取所有行的数据

回到前面的登录的例子,用txt文件来存放用户名和密码数据,通过读取该文件中的数据作为用例的测试数据。

文件名:user_info.txt

zhangsan,123

lis,456

wangwu,789

创建文件user_info.py

user_file = open('user_info.txt','r')

lines = user_file.readlines()

user_file.close()

for line in lines:

    username = line.split(',')[0]

    password = line.split(',')[1]

    print("username,password")

获取到的每一行数据通过split()方法拆分出用户名和密码,此方法还可以将一个字符串通过

某一个字符为分割点拆分成左右两部分,拆分出来的两部分以数组的形式存放。[0]取左部分[1]取右部分。

9.读取csv文件

创建info.csv文件,通过wps和excel创建表格,文件另存为csv格式进行保存,注意不要直接修改文件

后缀名创建csv文件,这样创建并非真正的csv类型的文件。创建A,B,C,D,E等列数。分别为[0][1][2][3][4]列

#读取文件,创建csv_read.py

import csv            #导入csv包

date = csv.reader(open('info.csv','r'))  #读取本地csv文件     reader和readlines的不同。

for user in date:                             #循环输出每一行信息

    print(user)

读取的每一行数据均是以数组的形式存在的。若取用户的某一列数据,只需指定数组下标即可。下标从0开始。

如果取第二列的数据,只把上述最后一句改为print(user[1])

10.读取xml文件

 xml被设计为传输和存储数据,其焦点是数据的内容。html被用来显示数据。

如果读取的数据是不规则的,例如:我们需要一个配置文件来配置当前自动化测试脚本的URL·浏览器·登陆的用户名和密码,

这时候就可以考虑选择使用XML文件来存放这些信息。

1.获取标签信息

from xml.dom import minidom             #导入xml的minidom模块

dom = minidom.parse('info.xml')            #parse()打开xml文档

root = dom.documentElement               #得到xml文件的唯一根元素

print(root.nodeName)                              #以下四个为节点属性

print(root.nodeValue)

print(root.nodeType)

print(rooot.ELEMENT_NODE)

2.获得任意标签名

from xml.dom import minidom             #导入xml的minidom模块

dom = minidom.parse('info.xml')            #parse()打开xml文档

root = dom.documentElement               #得到xml文件的唯一根元素

tagname = root.getElementsByTagName('browser')

print(tagname[0].tagname)

print(tagname[1].tagname)

ElementsByTagName():获取的标签以数组的形式存放,0表示第一个,1表示第二个。

3.获得标签的属性值

from xml.dom import minidom             #导入xml的minidom模块

dom = minidom.parse('info.xml')            #parse()打开xml文档

root = dom.documentElement               #得到xml文件的唯一根元素

logins = root.getElementsByTagName('login')  #获得标签名

username = login[0].getAttribute("username")  #获得第一个login标签的username属性值

print(username)

password = login[1].getAttribute("password")  #获得第二个login标签的password属性值

print(password)

 getAttribute()与webdriver中提供的get_attribute()方法相似。

4.获得标签对之间的数据

from xml.dom import minidom             #导入xml的minidom模块

dom = minidom.parse('info.xml')            #parse()打开xml文档

root = dom.documentElement               #得到xml文件的唯一根元素

 provinces = dom.getElementsByTagName('province')

p2 = provinces[1].firstChild.data                  #获得第二个province标签对的值

print(p2)

firstChild属性返回被选节点的第一个子节点,data表示获取该节点的数据,它与webdriver中提供的text方法类似。

11.Selenium IDE

 Selenium IDE是基于火狐浏览器的一个插件

安装方式:火狐浏览器下载地址输入:  http://docs.seleniumhq.org/download/

selenium ide的使用,录制与回放脚本,修改与编辑脚本,在脚本中添加断言与验证。

Selenium IDE一些常用命令的使用

1.open

command:open  ,target:http://localhost/  或/mypage ,value:空,在浏览器中打开url通过相对和绝对路径

2.click     以下target和value省略不写

command:click                 单击链接,按钮,复选和单选框。

                  clickAndWait    单击后需等待响应,用此命令

3.type

command:type  模拟键盘的输入,向指定的input中输入值,也适合给复选框和单选框赋值。

4.select

command:select  根据optionSpecifier选项选择器来选择一个下拉菜单选项。

5.goback

command:goBack   模拟单击浏览器的后退按钮。

6.selectWindow

command :selectWindow  选择一个弹出窗口。所有的命令会转移到被选择窗口中执行。

7.pause

command:pause  根据制定时间暂停selenium执行

8.fireEven

command:fireEven 模拟页面元素事件被激活的处理动作。

9.close

command:模拟单击浏览器关闭按钮

断言与验证

打开方法:首先打开selenium IDE ,在火狐浏览器上右击任意元素,选择最后一个选项 “show all available command”

可以获得四个命令:assert(断言),verify(验证),waitFor(等待),store(定义变量)

这四类命令又分为5中验证手段:

Title:获得页面标题

Value:获得元素的值

Text:获得元素的文本信息

Table:获得元素的标签

ElementPresent:获得当前元素

断言

如果使用断言,测试用例将会在断言失败后停止运行。

优点:直观的看到检查是否通过

缺点:若检查失败,后续的检查不会被执行,无法收集检查的结果状态。

测试用例:

command                                      target                                   value

open                                           http://www.baidu.com          

type                                           id=kw                                        selenium ide

click                                           id=su    

assertTitle                                 selenium ide_百度搜索

assertText                                 css=img[alt="到百度首页"]

assertElementPresent               css=img[alt="到百度首页"]

Title , Text,  ElementPresent 分别用来断言浏览器的标题,文本信息,和当前元素

验证

验证命令失败不会终止测试,测试会被执行完毕,不管是否发现缺陷

等待

pause:设置固定时间的休眠

waitFor:用于一定时间内等待某一元素的显示

比如:waitForTitle,waitForText,waitFor ElementPresent分别用来等待浏览器的标题,文本信息和当前元素

变量

store:用来定义变量

storeTitle : value为title;storeText:value为text  ,storeElementPresent:value为element。

可以通过定义的变量作为断言与验证的比较参数。 

12.Selenium Grid2

概念:利用Selenium Grid2 可以在不同的主机上建立主节点和分支节点,可以使主节点上的测试用例在不同的分支节点上运行。

          对于不同的节点可以搭建不同的测试环境(操作系统·浏览器)从而使一份测试用例得到不同环境下的执行结果。

环境配置: Grid2 不再提供单独的包,其功能已经集成到Selenium Server中,所以需要下载和运行Selenium Server才可以使用 Grid2的功能。

  1.下载Selenium Server              下载地址:http://www.seleniumhq.org/download/

      下载后得到selenium-server-standalone-xxx.jar,由于该jar包由java开发的,所以对jar包的运行需要java环境。

  2.配置java环境,下载JDK     下载地址:http://www.java.com/zh_CN/download/manual.jsp,下载完成后配置环境变量。

  3.运行 Selenium Server   通过java命令运行Selenium Server ,首先切换到Selenium Server 所在目录下并启动,在windows命令提示符(或linux终端)

     下启动Selenium Server 。  \selenium>   java -jar selenium-server-standalone-2.47.0.jar    

 Selenium Grid工作原理

Grid使用于进行分布式测试的工具,其结构是由一个hub主节点和若干个node代理节点组成。hub用来管理各个代理节点的注册和状态信息,并且接收

远程客户端代码的请求调用。然后把请求命令再转发给代理节点来执行。使用Grid远程执行测试的代码与直接调用Selenium Server是一样的,只是环境

启动的方式不一样,需要同时启动一个hub和至少一个node。

>    java -jar selenium-server-standalone-x.xx.x.jar -role hub  默认端口号:4444 

>    java -jar selenium-server-standalone-x.xx.x.jar -role node 或加(-port 5556) 默认端口号:5555  若有多个node,则需在后边指定端口号,直接写在后边即可。

通过浏览器访问Grid的控制台:http://localhost:4444/grid/console

Remote应用

WebDriver驱动分析

在selenium包的webdriver目录下有很多驱动,任何一个驱动的目录都有一个webdriver.py文件包括Firefox,Chrome,IE等等,

还包括remode,它不是支持某一款特定的浏览器或平台,而是一种配置模式,在这种配置模式下可以指定任意的平台或浏览器,

这种模式的执行都需要Selenium Server的支持。

 

相关文章: