学习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 ...
随机推荐
- ArrayList实现根据某属性大小相间排序
Java本身提供了一个集合的帮助类java.util.Collections,提供了对集合操作一些方法,借助于此类提供的sort方法可以实现对List进行排序操作 import java.util.A ...
- LevelDB初体验
近期工作须要找一个能使用磁盘存储数据,对写要求比較苛刻,须要每秒达100000TPS,读的时候须要能10000TPS左右,不能占用太多内存.单节点满足这个要求的常见有Redis.Memcached等, ...
- EF中的transaction的使用范例
注意一点: 在EF中使用事物后,对于一个新增的model,在saveChanges后,可以得到该实体的自增ID,但在提交事物之前, 该数据并没有真正的新增到DB中,但此时可以得到model新增的自增I ...
- English is very important!
Well, as a college student,I haven't realized how important the English is . But as a web programmer ...
- crawler_wireshark 过滤基础知识
一.IP过滤:包括来源IP或者目标IP等于某个IP比如:ip.src addr==192.168.0.208 or ip.src addr eq 192.168.0.208 显示来源IP ...
- crawler_解析之_jquery_语法选择器使用方法
爬虫解析一般使用 正则或者给予样式的 jquery语法选择器 正则是根本,类比jsoup基于dom,底层也有部分是基于正则实现的,linux操作系统 文本处理也是借助强大的正则体现的 .关于正则 请参 ...
- No bean named 'sessionFactory' is defined
1.错误叙述性说明 严重:Servlet service() for servlet default threw exception . org.springframework.beans.facto ...
- 项目管理实践 -- 健身小管家(Fitness housekeeper)的管理(5)(终结)
App已经上线了,应用宝上搜索“健身小管家”即可找到,不过存在几个问题:
- 深入Objective-C的动态特性 Runtime
Objective-C具有相当多的动态特性,基本的,也是经常被提到和用到的有动态类型(Dynamic typing),动态绑定(Dynamic binding)和动态加载(Dynamic loadin ...
- 12个有趣的c面试题目
1.gets()函数 问:请找出以下代码里的问题: #include<stdio.h> int main(void) { char buff[10]; memset ...