学习selenium python版最初的一个小想法
这个还是我在刚开始学习selenium的时候做的,自己觉得有点意思,在接下来我会基于目前我对于selenium的一些深入研究,写下我对selenium的理解以及UIAutomation的一些理解,以此开篇吧^_^
前段时间研究Selenium,写了一些测试网页的代码,写着写着,就感觉这些自动化cases的相似度太高,多数是大同小异,基本上可以归纳为这样三步1)找到元素 2)进行操作, 比如点击或者滑动 3) 验证期望, 比如跳转到了一个新页面,或者新元素出现在屏幕中.
比如下面:
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
def web_automation():
browser=webdriver.Chrome()
browser.get('http://www.baidu.com/') Input_element=browser.find_element_by_id('kw')
Input_element.send_keys('Selenium')
browser.find_element_by_id('su').click()
result=browser.find_element_by_xpath('//*[@id="container"]/div[2]').is_displayed() assert result!=True,"Failed"
写的多了,这时候就想,能不能有什么模板,让我们快速的创建一条case,甚或者能让一个不会Selenium的Tester也能写自动化case呢。
说做就做,最后就搞出来了下面一个雏形, 我们可以定义这样的一个XML:
<TestCase name="ClickBackButton" scriptVersion="1.0.0">
<Executable>Chrome</Executable>
<Address>http://www.baidu.com</Address>
<Action Operate="InputSearchInfo" Type="Input" ID="kw" Content="Glow"/>
<Action Operate="Scroll" Type="Scroll" />
<Action Operate="ClickNextPageHLink" Type="Click" XPath='//*[@id="page"]/a[10]'>
<Expected XPath='//*[@id="page"]/strong/span[2]' Text="2" />
</Action>
<Action Operate="Goback" Type="Back">
<Expected XPath='//*[@id="page"]/strong/span[2]' Text="1" />
</Action>
<Action Operate="Scroll" Type="Scroll" />
<Action Operate="ClickPage6" Type="Click" XPath='//*[@id="page"]/a[5]'>
<Expected XPath='//*[@id="page"]/strong/span[2]' Text="6" />
</Action>
<Action Operate="Goback" Type="Back">
<Expected XPath='//*[@id="page"]/strong/span[2]' Text="1" />
</Action>
</TestCase>
然后我们就可以这样来解析:
第一步解析XML生成TestCase的list,在例子中就一个Testcase:
import xml.etree.ElementTree as ET
import logging
import os
import sys
import traceback
from TestCase import TestCase class ParseCase:
def __init__(self,xml_path):
if os.path.exists(os.getcwd()+"\\"+xml_path) or os.path.exists(xml_path):
self.caseList=[]
try:
xml=ET.parse(xml_path)
root=xml.getroot()
self.caseList=root.find('TestList').findall('TestCase')
except IOError as e:
print traceback.format_exc()
logging.debug(traceback.format_exc())
if self.caseList:
logging.info('No Testcase detected')
else:
logging.info('No Testcase detected')
else:
print "XML file is not exists"
logging.debug("XML file is not exists") def getAllTestCaseList(self):
TestCases=[]
for case in self.caseList:
_testcase=TestCase(case)
TestCases.append(_testcase)
return TestCases
第二步, 根据每个testcase建立TestCase类的实例:
class TestCase:
def __init__(self, _testcase):
self.name=_testcase.attrib['name']
_list=[]
self.actions=[]
try:
_list=_testcase.getchildren()
except Exception,msg:
print msg
self._executor=_testcase.find('Executable').text
self.address=_testcase.find('Address').text
for act in _testcase.findall('Action'):
if act.tag=='Action':
_action=Action(act)
self.actions.append(_action) def setUp(self):
if 'Chrome'==self._executor:
self.executor=webdriver.Chrome()
elif 'Firefox'==self._executor:
self.executor=webdriver.Firefox()
else:
self.executor=webdriver.Ie()
self.executor.get(self.address) def tearDown(self):
self.executor.quit() def execute(self):
logging.debug("Start to execute the testcase:%s" % self.name)
print "TestCaseName:%s" % self.name
try:
self.setUp()
for action in self.actions:
action.execute(self.executor);
self.tearDown()
Assert.AssertPass("TestCase:%s " % self.name)
except Exception as error:
print error
self.tearDown()
Assert.AssertFail("TestCase:%s " % self.name)
第三步,根据xml里定义的type来触发动作,我就简单的列了下:
def execute(self,executor):
_type=self._actions['Type']
self.getBy(self._actions)
try:
if self.by!=None:
ele=self.findElement(executor)
Assert.AssertIsNotNull(ele," ".join("Find element by %s:%s" % (str(self.by),self.by_value)))
if _type=='Input':
ele.send_keys(self._actions['Content'])
time.sleep(3) elif _type=='Click':
ele.click()
elif _type=='Scroll':
webOperate.page_scroll(executor)
elif _type=='Back':
webOperate.goBack(executor) else:
print " ",
Assert.AssertFail(self._name)
print "No such action:%s" % _type
if self._expected is not None:
Assert.AssertIsTrue(self.isExpected(executor)," ".join("Find element by %s:%s" % (str(self.by),self.by_value)))
print " ",
Assert.AssertPass(self._name)
except AssertionError:
print " ",
Assert.AssertFail(self._name)
raise AssertionError(self._name +" execute failed")
看一个运行的截图

代码比较简单,原理也很清晰,就是解析XML文件,然后调用相应的selenium代码,但是如果我们再深入的想想,在解析这些XML的时候,是不是可以以更友好的方式来展示生成的代码呢,甚或者以UI的方式,一条条展示。然后再提供可编辑功能?甚或者再提供录制的方式来自动生成这些XML文件,再解析成代码,这不就是一个强大的自动化测试工具??
学习selenium python版最初的一个小想法的更多相关文章
- 数据科学的完整学习路径—Python版(转载)
时间 2015-01-29 14:14:11 数盟原文 http://dataunion.org/?p=9805 译者: Allen 从Python菜鸟到Python Kaggler的旅程(译注: ...
- python新手第一天学习笔记-python循环控制和第一个python小游戏
Python的三种逻辑控制 1.python语法. python 是以缩进作为基本判断的.同一代码缩进需要保持一致.否则会报错 1.if 的三种循环 _age = 53 # 注意,input接受的都是 ...
- python练习册 每天一个小程序 第0000题
PIL库学习链接:http://blog.csdn.net/column/details/pythonpil.html?&page=1 1 #-*-coding:utf-8-*- 2 __au ...
- extJs学习基础5 理解mvvm的一个小案例
今天很是幸运,看到了一位大神的博客,学习了不少的东西.太感谢了.(满满的都是爱啊) 建议去学习这个大神的博客,真心不错. 博客地址:http://blog.csdn.net/column/detail ...
- Python数学运算的一个小算法(求一元二次方程的实根)
请定义一个函数quadratic(a, b, c),接收3个参数,返回一元二次方程:ax² + bx + c = 0的两个解. #!/usr/bin/env python # -*- coding: ...
- python练习册 每天一个小程序 第0013题
# -*-coding:utf-8-*- ''' 题目描述: 用 Python 写一个爬图片的程序,爬 这个链接里的日本妹子图片 :-) 地址: http://tieba.baidu.com/p/21 ...
- python练习册 每天一个小程序 第0001题
1 # -*-coding:utf-8-*- 2 __author__ = 'Deen' 3 ''' 4 题目描述: 5 做为 Apple Store App 独立开发者,你要搞限时促销,为你的应用生 ...
- JAVA学习笔记(一):一个小爬虫的例子
1.import java.io.*; java.io.*不是一个文件,而是一组类.它是在java.io包里的所有类,*是通配符,比如a*.txt代表的就是以a开头的所有txt文件,“?”是单个词 ...
- windows平台python svn模块的一个小 bug
环境 编程语言版本:python 2.7 操作系统:win10 64位 模块名:svn svn checkout时报错 File "D:\Python27\lib\site-package ...
随机推荐
- poj3417 Network 树形Dp+LCA
题意:给定一棵n个节点的树,然后在给定m条边,去掉m条边中的一条和原树中的一条边,使得树至少分为两部分,问有多少种方案. 神题,一点也想不到做法, 首先要分析出加入一条边之后会形成环,形成环的话,如果 ...
- YUV422蓝色屏幕输出的调试援助
YUV422蓝色屏幕输出的调试援助 YUV422有YUYV,YVYU,UYVY,VYUY四种,以下笔者就就以UYVY为例介绍一下数据构成.因为常常要跟视频输入打交道,所以YUV422这种常见的视频信号 ...
- Java 反射 想
所谓反射.是指在执行时状态中,获取类中的属性和方法.以及调用当中的方法的一种机制. 这样的机制的作用在于获取执行时才知道的类(Class)及当中的属性(Field).方法(Method)以及调用当中的 ...
- hdu 4972 A simple dynamic programming problem(高效)
pid=4972" target="_blank" style="">题目链接:hdu 4972 A simple dynamic progra ...
- crawler_基础之_java.net.HttpURLConnection 访问网络资源
java访问网络资源 由底层到封装 为 scoket==> java.net.HttpURLConnection==>HttpClient 这次阐述先 java.net.HttpURL ...
- 基于 Android 的 3D 视频样本代码
作者:Mark Liu 下载样本代码 简单介绍 在Android 中,创建一个可以播放视频剪辑的应用很easy:创建一个採用 3D 图形平面的游戏应用也很easy.可是,创建一个可以在 3D 图形对象 ...
- java_Eclipse主题颜色配置+全屏
http://www.eclipsecolorthemes.org/ 这个是主题的网站. 在Eclipse里, File->Import->General->Preferences- ...
- iOS开发之protocol和delegate
protocol--协议 协议是用来定义对象的属性,行为和用于回调的. 协议中有两个keyword@private和@optional,@private表示使用这个协议必需要写的方法,@op ...
- POJ2771_Guardian of Decency(二分图/最大独立集=N-最大匹配)
解决报告 http://blog.csdn.net/juncoder/article/details/38159017 题目传送门 题意: 看到题目我就笑了.., 老师觉得这种两个学生不是一对: 身高 ...
- Linux应用环境
转载Linux应用环境 阅读目录 引言 使用 Linux 的一些困难和解决方法 我眼中的Linux哲学总纲 我这一系列随笔中展现出的Linux哲学 Linux之得和Linux之失 总结 回到顶部 引言 ...