Appium+Python+lub

简介: Appium+Python+lub

随着敏捷的普及BDD已经越来越受到大家的认识了,BDD目前比较常用的技术是Cucumber框架,而在Python语言,Cucumber主要包括lettuceBehaveFreshen。而lettuce是大家用的比较多的,但是要测试APP或者WEB就需要在lettuce上安装一个lub插件。由于BDDCucumberlettuce技术在网上的资料非常多,所以本文不进行介绍,本文主要介绍Appium+Python+lub,而对于如何使用lub测试WEB,请参看http://www.diggerplus.org/archives/3623


要使用lub,必须进行如下操作:

  1. 下载Python 2.X版本(建议2.7lettuce不支持Python 3.X
  2. https://github.com/qddegtya/Lub下载Lub
  3. 进入文件夹安装相关插件“>pip install -r requirements.txt
  4. 安装lub,同时也安装了lettuce:“>python setup.py install
  5. 在工作区域运行命令“>lub -i gen

经过上述的操作在工作区域生成了如图一的三个文件夹。


image.png

图一 lub工作区域的文件夹


其中:

  • apptc用于测试APP程序;
  • webtc用于测试WEB程序。

不管在apptc还是webpc下都包含以下三个文件夹

  • features:该文件夹下的all.feature为特性描述文件;
  • step_definition:该文件夹下的steps.py为步骤文件;
  • support:该文件夹下的terrain.py为全局控制。

在这里我们先来介绍一下我们这个被测APP产品。

 image.png       image.png  

  图二:登录首页                             图三:注册页                

image.png

 图四:登录成功页


图二为登录首页,当输入用户名和密码后,点击【登录】按钮,如果用户名密码正确进入图四登录成功页面,否则弹出错误消息;点击【进行注册】按钮进入图三进行注册;点击【清除】按钮,清除数据库中的所有数据,这个按钮是为测试而临时设置的,正式产品中将会取消。


图三为注册页,当输入用户名和密码后,点击【注册】按钮,当输入的用户名在数据库中不存在,注册成功,返回图二的登录页面,否则弹出错误消息。


图四为登录成功页,当在图二中输入正确的用户名和密码后,进入这个页面,这里的“Hello world”将变为“Welcome +用户名。


首先让我们来看一下描述文件,features文件夹下的all.feature文件。

Feature: testcase
         Scenario:  Demo4 APP
         Give  click at "id" for "com.example.demo4:id/button3" to clear  database
         And  click at "id" for "com.example.demo4:id/button2" to  prepare rangiest
         And  at "id" for "com.example.demo4:id/username1" enter  username "" to clear rangiest username edit field
         And  at "id" for "com.example.demo4:id/username1" enter  username "Jerry"
         And  at "id" for "com.example.demo4:id/password1" enter  password "" to clear rangiest password edit field
         And  at "id" for "com.example.demo4:id/password1" enter  password "123456"
         Then  I finish to regiest,then click at "id" for  "com.example.demo4:id/button11"
         Given  at "id" for "com.example.demo4:id/username" enter  username "" to clear login username edit field
         And  at "id" for "com.example.demo4:id/username" enter  username "Jerry"
         And  at "id" for "com.example.demo4:id/password" enter  password "" to clear login password edit field
         And  at "id" for "com.example.demo4:id/password" enter  password "123456"
         And  click at "id" for "com.example.demo4:id/button1"
         Then  I have been logined,and can click at "id" for  "com.example.demo4:id/logout"
         click  at "id" for "com.example.demo4:id/button3" to clear  database fannily


其中FeatureScenarioGivenThenAndBDD的关键字,包括以下几个:

  • Given假设
  • When时间
  • Then下一步
  • And
  • Feature特性:
  • Background背景:
  • Scenario场合大纲:

然后我们来看一下support文件夹下的下的terrain.py文件。

# -*- coding:utf-8 -*-
# controls
from lettuce import *
from nose.tools import assert_equals
from appium import webdriver
@before.each_scenario
def startupdriver(scenario):
         world.desired_caps  = {}
         world.desired_caps['platformName']  = 'Android'
         world.desired_caps['platformVersion']  = '6.0'
         world.desired_caps['deviceName']  = 'Android Emulator'
         world.desired_caps['appPackage']  = 'com.example.demo4'
         world.desired_caps['appActivity']  = '.MainActivity'
         world.driver  = webdriver.Remote('http://localhost:4723/wd/hub', world.desired_caps)


world.XXX:表示这个变量是个全局变量,他可以跨越terrain.py文件和step_definition文件夹下的下的steps.py文件进行参数传递。


在这里@before.each_scenario表示在每个场景执行前进行,有点像JUnit框架中的@before,或者更像TestNG,因为它包含以下一系列标签:

  • @before.all
  • @after.all
  • @before.each_feature
  • @after.each_feature
  • @before.each_scenario
  • @after.each_scenario
  • @before.each_outline
  • @after.each_outline
  • @before.each_step
  • @after.each_step

最后我们来看一下step_definition文件夹下的下的steps.py文件。


# -*-  coding:utf-8 -*-
# step  definitions
from  lettuce import *
from  nose.tools import assert_equals
from  appium import webdriver
from  Lub.webtools.actions import *
@step(u'click  at "(.*)" for "(.*)" to clear database')
def  exemplify_world(step,typename,typekey):
     lubclick(lubfind(world.driver,typename,typekey))
@step(u'click  at "(.*)" for "(.*)" to prepare regiest')
def  exemplify_world(step,typename,typekey):
    lubclick(lubfind(world.driver,typename,typekey))
@step(u'at  "(.*)" for "(.*)" enter username (.*) to clear regiest  username edit field')
def  enter_username(step,typename,typekey,typeval):
     lubinput(lubfind(world.driver,typename,typekey),typeval)
@step(u'at  "(.*)" for "(.*)" enter username "(.*)"')
def  enter_username(step,typename,typekey,typeval):
     lubinput(lubfind(world.driver,typename,typekey),typeval)
@step(u'at  "(.*)" for "(.*)" enter password "(.*)" to  clear regiest password edit field')
def  enter_username(step,typename,typekey,typeval):
     lubinput(lubfind(world.driver,typename,typekey),typeval)
@step(u'at  "(.*)" for "(.*)" enter password "(.*)"')
def  enter_username(step,typename,typekey,typeval):
     lubinput(lubfind(world.driver,typename,typekey),typeval)
@step(r'I  finish to regiest,then click at "(.*)" for "(.*)"')
def  exemplify_world(step,typename,typekey):
     lubclick(lubfind(world.driver,typename,typekey))
@step(u'at  "(.*)" for "(.*)" enter username "(.*)" to  clear login username edit field')
def  enter_username(step,typename,typekey,typeval):
     lubinput(lubfind(world.driver,typename,typekey),typeval)
@step(u'at  "(.*)" for "(.*)" enter username "(.*)"')
def  enter_username(step,typename,typekey,typeval):
     lubinput(lubfind(world.driver,typename,typekey),typeval)
@step(u'at  "(.*)" for "(.*)" enter password "(.*)" to  clear login password edit field')
def  enter_password(step,typename,typekey,typeval):
      lubinput(lubfind(world.driver,typename,typekey),typeval)
@step(u'at  "(.*)" for "(.*)" enter password "(.*)"')
def  enter_password(step,typename,typekey,typeval):
      lubinput(lubfind(world.driver,typename,typekey),typeval)
@step(u'click  at "(.*)" for "(.*)"')
def  login(step,typename,typekey):
    lubclick(lubfind(world.driver,typename,typekey))
@step(u'I  have been logined,and can click at "(.*)" for "(.*)"')
def  login(step,typename,typekey):
     lubclick(lubfind(world.driver,typename,typekey))
@step(r'at  "(.*)" for "(.*)" to clear database fannily')
def  exemplify_world(step,typename,typekey):
     lubclick(lubfind(world.driver,typename,typekey))


@step(u'clickat "(.*)" for "(.*)" to prepare regiest')

u后引号中的为feature中对应的一个GiveAndThen语句,在语句中用(.*)代表变量,在函数中用一个变量代替,比如:

@step(u'click at "(.*)" for  "(.*)" to prepare regiest')
def  exemplify_world(step,typename,typekey):


第一个(.*)代表变量typename(比如id),第二个(.*)代表变量typekey(比如com.example.demo4:id/button2

lubclick(lubfind(world.driver,typename,typekey))


代表在typename下寻找值为,typekey,然后进行点击操作

lubinput(lubfind(world.driver,typename,typekey),typeval)


代表在typename下寻找值为,typekey,然后在这个控件下输typeval

关于这方面的资料国内非常奇缺,大家可以到http://lettuce.it/网上去了解详细全面的资料。


在这里大家是否觉得all.feature文件不太适合专业的业务人员来书写,因为它与UI进行了捆绑。对的,大家如果想到了这一点是对BDD有了比较深刻的了解,我之所以这样写是为了让大家对lub有个深刻的印象,现在我们来改造一下这个文件。

Feature:  testcase
         Scenario: Demo4 APP
         Give click reset button to clear  database
         And click register button prepare  register
         And clear register username edit  field
         And enter username "Jerry"  at username register field
         And clear register password edit  field
         And enter password "123456"  at password register field
         Then click register field after  finish to register
          Give enter username "Jerry" at  username login field
         And clear login password edit field
         And enter password "123456"  at password login field
         Then click login field after finish  to register
         And click login button
         And I have been logined, and I can  click logout button
         Then click reset button to clear  database for finish test


这样写就比较正常了,但是我们又应该如何书写对应的steps.py文件呢?在这里给大家一个小小的提示。

step(u'enter username "(.*)" at  username register field')
def enter_username(step,typeval):
     lubinput(lubfind(world.driver,"id","com.example.demo4:id/username1"),typeval)


这样我们由feature对应UI变成了steps.py文件对应UI了。由于all.feature文件是由业务人员所写的,所以后者比较可靠。


顾翔凡言:

软件的基本功能质量应该主要由开发人员负责,测试人员的主要责任在于非功能质量,比如:性能、易用性、可靠性。以及边缘问题及深层问题,边缘问题及深层问题主要靠探索式测试完成

目录
相关文章
|
1月前
|
数据采集 测试技术 API
python爬虫之Appium 的使用
搭建appium环境,appium基本使用,API操作等等
46 0
|
7月前
|
JSON Java 测试技术
Python + Appium 自动化操作微信入门
Python + Appium 自动化操作微信入门
139 0
|
1月前
|
数据采集 JSON NoSQL
python爬虫 Appium+mitmdump 京东商品
python 爬虫 Charles + appium + mitmproxy 实现 app 京东商品数据获取
32 0
|
3月前
|
JavaScript Java 开发工具
Python+Appium2.0的APP自动化环境搭建
Python+Appium2.0的APP自动化环境搭建
111 0
|
3月前
|
Python
python 使用 AppiumService 类启动appium server
python 使用 AppiumService 类启动appium server
52 0
|
3月前
|
Python
Python Appium Selenium 查杀进程的实用方法
Python Appium Selenium 查杀进程的实用方法
35 1
|
7月前
|
JSON Java 测试技术
Python + Appium 自动化操作微信入门看这一篇就够了
Python + Appium 自动化操作微信入门看这一篇就够了
536 0
Python + Appium 自动化操作微信入门看这一篇就够了
|
8月前
|
监控 网络协议 Python
appium--python启动appium服务
appium--python启动appium服务
|
Java 测试技术 开发工具
自动化测试 Appium之Python运行环境搭建 Part2
自动化测试 Appium之Python运行环境搭建 Part2
92 0
|
JavaScript Java 测试技术
自动化测试 Appium之Python运行环境搭建 Part1
自动化测试 Appium之Python运行环境搭建 Part1
71 0

热门文章

最新文章