AppiumTest搭建

0.说明:

演示均为真机,不是模拟器

软件自行安装

1.框架结构

  • 业务功能的封装
  • 测试用例封装
  • 测试包管理
  • 截图处理
  • 断言处理
  • 日志获取
  • 测试报告生成
  • 数据驱动
  • 数据配置

2.代码搭建

driver配置封装

lyf_caps.yaml 配置表

 desired_caps.py

import yaml
import logging.config
from appium import webdriver
import os

CON_LOG = '../config/log.conf'
logging.config.fileConfig(CON_LOG)
logging = logging.getLogger()

def appium_desired():

    with open('../config/lyf_caps.yaml','r',encoding='utf-8') as file:
        data = yaml.load(file)

    desired_caps={}
    desired_caps['platformName']=data['platformName']

    desired_caps['platformVersion']=data['platformVersion']
    desired_caps['deviceName']=data['deviceName']

    base_dir = os.path.dirname(os.path.dirname(__file__))
    app_path = os.path.join(base_dir, 'app', data['appname'])
    desired_caps['app'] = app_path

    desired_caps['noReset']=data['noReset']

    desired_caps['unicodeKeyboard']=data['unicodeKeyboard']
    desired_caps['resetKeyboard']=data['resetKeyboard']

    desired_caps['appPackage']=data['appPackage']
    desired_caps['appActivity']=data['appActivity']

    logging.info('start run app...')
    driver = webdriver.Remote('http://'+str(data['ip'])+':'+str(data['port'])+'/wd/hub', desired_caps)

    driver.implicitly_wait(5)
    return driver

 基类封装

baseView.py

common公共模块封装

公共方法封装 : common_fun.py

from  baseView.baseView import BaseView
from common.desired_caps import appium_desired
from selenium.common.exceptions import NoSuchElementException
import logging.config
from selenium.webdriver.common.by import By
import os
import time
import csv


class Common(BaseView):
	# 取消升级和跳过引导按钮
	cancel_upgradeBtn = (By.ID, 'android:id/button2')
	skipBtn = (By.ID, 'com.tal.lyf:id/tv_skip')

	# 登录后浮窗广告取消按钮
	wemedia_cacel = (By.ID, 'com.tal.lyf:id/view_wemedia_cacel')

	def check_updateBtn(self):
		logging.info("============check_updateBtn===============")

		try:
			element = self.driver.find_element(*self.cancel_upgradeBtn)
		except NoSuchElementException:
			logging.info('update element is not found!')
		else:
			logging.info('click cancelBtn')
			element.click()

	def check_skipBtn(self):
		logging.info("==========check_skipBtn===========")
		try:
			element = self.driver.find_element(*self.skipBtn)
		except NoSuchElementException:
			logging.info('skipBtn element is not found!')
		else:
			logging.info('click skipBtn')
			element.click()

	def get_screenSize(self):
		'''
		获取屏幕尺寸
		:return:
		'''
		x = self.get_window_size()['width']
		y = self.get_window_size()['height']
		return (x, y)

	def swipeLeft(self):
		logging.info('swipeLeft')
		l = self.get_screenSize()
		y1 = int(l[1] * 0.5)
		x1 = int(l[0] * 0.95)
		x2 = int(l[0] * 0.25)
		self.swipe(x1, y1, x2, y1, 1000)

	def getTime(self):
		self.now = time.strftime("%Y-%m-%d %H_%M_%S")
		return self.now

	def getScreenShot(self, module):
		time = self.getTime()
		image_file = os.path.dirname(os.path.dirname(__file__)) + '/screenshots/%s_%s.png' % (module, time)

		logging.info('get %s screenshot' % module)
		self.driver.get_screenshot_as_file(image_file)

	def check_market_ad(self):
		'''检测登录或者注册之后的界面浮窗广告'''
		logging.info('=======check_market_ad=============')
		try:
			element = self.driver.find_element(*self.wemedia_cacel)
		except NoSuchElementException:
			pass
		else:
			logging.info('close market ad')
			element.click()

	def get_csv_data(self, csv_file, line):
		'''
		获取csv文件指定行的数据
		:param csv_file: csv文件路径
		:param line: 数据行数
		:return:
		'''
		with open(csv_file, 'r', encoding='utf-8-sig') as file:
			reader = csv.reader(file)
			for index, row in enumerate(reader, 1):
				if index == line:
					return row

业务模块封装

1.登录页面业务逻辑模块

loginView.py

import logging
from common.desired_caps import appium_desired
from common.common_func import Common, By
from selenium.common.exceptions import NoSuchElementException


class LoginView(Common):
	# 登录界面元素
	username_type = (By.ID, 'com.tal.lyf:id/login_email_edittext')
	password_type = (By.ID, 'com.tal.lyf:id/login_password_edittext')
	loginBtn = (By.ID, 'com.tal.lyf:id/login_login_btn')

	# 个人中心元素
	username = (By.ID, 'com.tal.lyf:id/activity_usercenter_username')
	button_myself = (By.ID, 'com.tal.lyf:id/mainactivity_button_mysefl')

	# 个人中心下线警告提醒确定按钮
	commitBtn = (By.ID, 'com.tal.lyf:id/tip_commit')

	# 退出操作相关元素
	settingBtn = (By.ID, 'com.tal.lyf:id/myapptitle_RightButtonWraper')
	logoutBtn = (By.ID, 'com.tal.lyf:id/setting_logout_text')
	tip_commit = (By.ID, 'com.tal.lyf:id/tip_commit')

	def login_action(self, username, password):
		self.check_updateBtn()
		self.check_skipBtn()

		logging.info('============login_action==============')
		logging.info('username is:%s' % username)
		self.driver.find_element(*self.username_type).send_keys(username)

		logging.info('password is:%s' % password)
		self.driver.find_element(*self.password_type).send_keys(password)

		logging.info('click loginBtn')
		self.driver.find_element(*self.loginBtn).click()
		logging.info('login finished!')

	def check_account_alert(self):
		'''检测账户登录后是否有账户下线提示'''
		logging.info('====check_account_alert======')
		try:
			element = self.driver.find_element(*self.commitBtn)
		except NoSuchElementException:
			pass
		else:
			logging.info('click commitBtn')
			element.click()

	def check_loginStatus(self):
		logging.info('==========check_loginStatus===========')
		self.check_market_ad()
		self.check_account_alert()

		try:
			self.driver.find_element(*self.button_myself).click()
			self.driver.find_element(*self.username)
		except NoSuchElementException:
			logging.error('login Fail!')
			self.getScreenShot('login Fail')
			return False
		else:
			logging.info('login success!')
			l.logout_action()
			return True

	def logout_action(self):
		logging.info('=========logout_action==========')
		self.driver.find_element(*self.settingBtn).click()
		self.driver.find_element(*self.logoutBtn).click()
		self.driver.find_element(*self.tip_commit).click()

注册页面业务逻辑封装

registerView.py

主页页面业务逻辑封装

myHomeView.py

订单页面业务逻辑封装

orderView.py

退出页面业务逻辑封装

quitView.py

骑手页面业务逻辑封装

riderView.py

门店页面业务逻辑封装

shopView.py

...自行封装 哈哈哈哈

config文件配置

日志文件配置 log.config

[loggers]
keys=root,infoLogger

[logger_root]
level=DEBUG
handlers=consoleHandler,fileHandler

[logger_infoLogger]
handlers=consoleHandler,fileHandler
qualname=infoLogger
propagate=0

[handlers]
keys=consoleHandler,fileHandler

[handler_consoleHandler]
class=StreamHandler
level=INFO
formatter=form02
args=(sys.stderr,)

[handler_fileHandler]
class=FileHandler
level=INFO
formatter=form01
args=('../logs/mylog.log', 'a')

[formatters]
keys=form01,form02

[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s

[formatter_form02]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s

测试用例封装

1.测试用例执行开始结束操作封装myunit.py

 2.注册用例:test_register.py

 3.登录用例

test_login.py

from common.myunit import StartEnd
from businessView.loginView import LoginView
import unittest
import logging


class LoginTest(StartEnd):
    csv_file = '../data/account.csv'

    # @unittest.skip("test_login_zzzz")
    def test_login_zxw2017(self):
        logging.info('==========test_login_zzzz========')
        l=LoginView(self.driver)
        data = l.get_csv_data(self.csv_file,1)

        l.login_action(data[0],data[1])
        self.assertTrue(l.check_loginStatus())

    # @unittest.skip('skip test_login_yyyy')
    def test_login_zxw2018(self):
        logging.info('=========test_login_yyyy============')
        l=LoginView(self.driver)
        data = l.get_csv_data(self.csv_file,2)

        l.login_action(data[0],data[1])
        self.assertTrue(l.check_loginStatus())

    # @unittest.skip("test_login_erro")
    def test_login_erro(self):
        logging.info('=======test_login_erro=========')
        l=LoginView(self.driver)
        data = l.get_csv_data(self.csv_file, 3)

        l.login_action(data[0], data[1])
        self.assertTrue(l.check_loginStatus(),msg='login fail!')

4.其他模块用例自行编写

执行测试用例&报告生成

 后续可结合jenkins持续集成运行。

附录架构说明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值