Appium自动化测试框架如下图:

框架中包含的脚本以此如下展示:

1.app目录下存放着测试需要的apk包

2.baseView目录下脚本中封装着所有页面需要的方法

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019-07-04 17:17
# @Author : zhouyang
# @File : baseView.py


class BaseView(object):
    def __init__(self,driver):
        self.driver=driver
    def find_element(self,*loc):
        return self.driver.find_element(*loc)
    def find_elements(self,*loc):
        return self.driver.find_elements(*loc)
    def get_window_size(self):
        return self.driver.get_window_size()
    def swipe(self,start_x,start_y,end_x,end_y,duration):
        return self.driver.swipe(start_x,start_y,end_x,end_y,duration)

3.businessView目录下存放着所有页面具体实现的方法,比如登录页面,注册页面

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019-07-05 11:42
# @Author : zhouyang
# @File : loginView.py

from common.desired_caps import appium_desired
from common.commom_fun import Commom
import logging
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException


class LoginView(Commom):
    username_type=(By.ID,\'com.tal.kaoyan:id/login_email_edittext\')
    password_type=(By.ID,\'com.tal.kaoyan:id/login_password_edittext\')
    submit_type=(By.ID,\'com.tal.kaoyan:id/login_login_btn\')

    tip_commit=(By.ID,\'com.tal.kaoyan:id/tip_commit\')

    button_mysefl=(By.ID,\'com.tal.kaoyan:id/mainactivity_button_mysefl\')
    usercenter_username=(By.ID,\'com.tal.kaoyan:id/activity_usercenter_username\')

    RightButton_textview=(By.ID,\'com.tal.kaoyan:id/myapptitle_RightButton_textview\')
    logout_text=(By.ID,\'com.tal.kaoyan:id/setting_logout_text\')


    def login_action(self,username,password):
        self.check_cancleBtn()
        self.check_skipBtn()
        logging.info(\'=================login===================\')
        logging.info(\'input username:%s\'%username)
        self.driver.find_element(*self.username_type).send_keys(username)

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

        logging.info(\'click loginBtn\')
        self.driver.find_element(*self.submit_type).click()
        logging.info(\'===============login finish==============\')

    def check_account_alert(self):
        logging.info(\'========check_account_alert==========\')
        try:
            element=self.driver.find_element(*self.tip_commit)
        except NoSuchElementException:
            pass
        else:
            logging.info(\'=======close alert=======\')
            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_mysefl).click()
            element=self.driver.find_element(*self.usercenter_username)
        except NoSuchElementException:
            logging.error(\'========login false=========\')
            self.get_screenshot(\'login fail\')
            return False
        else:
            logging.info(\'=========login success==========\')
            self.logout_action()
            return True

    def logout_action(self):
        logging.info(\'=========logout action=========\')
        self.driver.find_element(*self.RightButton_textview).click()
        self.driver.find_element(*self.logout_text).click()
        self.driver.find_element(*self.tip_commit).click()


if __name__ == \'__main__\':
    driver=appium_desired()
    l=LoginView(driver)
    l.login_action(\'自学网2018\',\'zxw208\')
    l.check_loginStatus()

        
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019-07-18 11:50
# @Author : zhouyang
# @File : register.py
\'\'\'注册模块\'\'\'

from common.commom_fun import Commom
from common.desired_caps import appium_desired
import logging
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from random import randint

class RegisterVeiw(Commom):
    register_text=(By.ID,\'com.tal.kaoyan:id/login_register_text\')

    register_userheader=(By.ID,\'com.tal.kaoyan:id/activity_register_userheader\')
    item_image=(By.ID,\'com.tal.kaoyan:id/item_image\')
    save=(By.ID,\'com.tal.kaoyan:id/save\')

    register_username=(By.ID,\'com.tal.kaoyan:id/activity_register_username_edittext\')
    register_password=(By.ID,\'com.tal.kaoyan:id/activity_register_password_edittext\')
    register_email=(By.ID,\'com.tal.kaoyan:id/activity_register_email_edittext\')
    register_btn=(By.ID,\'com.tal.kaoyan:id/activity_register_register_btn\')

    perfectinfomation_time=(By.ID,\'com.tal.kaoyan:id/activity_perfectinfomation_time\')
    text1=(By.ID,\'android:id/text1\')

    school_name=(By.ID,\'com.tal.kaoyan:id/perfectinfomation_edit_school_name\')
    forum_title=(By.ID,\'com.tal.kaoyan:id/more_forum_title\')
    university=(By.ID,\'com.tal.kaoyan:id/university_search_item_name\')

    perfectinfomation_major=(By.ID,\'com.tal.kaoyan:id/activity_perfectinfomation_major\')
    subject=(By.ID,\'com.tal.kaoyan:id/major_subject_title\')
    group=(By.ID,\'com.tal.kaoyan:id/major_group_title\')
    search_item=(By.ID,\'com.tal.kaoyan:id/major_search_item_name\')

    perfectinfomation_goBtn=(By.ID,\'com.tal.kaoyan:id/activity_perfectinfomation_goBtn\')

    button_mysefl = (By.ID, \'com.tal.kaoyan:id/mainactivity_button_mysefl\')
    usercenter_username = (By.ID, \'com.tal.kaoyan:id/activity_usercenter_username\')


    def register_action(self,username,password,email):
        logging.info(\'========register_action=========\')
        self.check_cancleBtn()
        self.check_skipBtn()
        self.driver.find_element(*self.register_text).click() #点击注册

        #添加头像
        logging.info(\'set userheader\')
        self.driver.find_element(*self.register_userheader).click()
        self.driver.find_elements(*self.item_image)[1].click()
        self.driver.find_element(*self.save).click()

        #填写用户名、密码、Email
        logging.info(\'username is %s\'%username)
        self.driver.find_element(*self.register_username).send_keys(username)

        logging.info(\'password is %s\' % password)
        self.driver.find_element(*self.register_password).send_keys(password)

        logging.info(\'email is %s\' % email)
        self.driver.find_element(*self.register_email).send_keys(email)

        # 点击立即注册
        logging.info(\'register\')
        self.driver.find_element(*self.register_btn).click()

        #判断是否进入注册信息页面
        try:
            self.driver.find_element(*self.perfectinfomation_time)
        except NoSuchElementException:
            logging.error(\'regiter fail\')
            self.get_screenshot(\'regiter fail\')
            return False
        else:
            self.add_register_info()
            if self.check_registerStatus():
                return True
            else:
                return False

    def add_register_info(self):
        logging.info(\'=======add_register_info=======\')
        #填写年份
        self.driver.find_element(*self.perfectinfomation_time).click()
        self.driver.find_elements(*self.text1)[1].click() #2015

        #选择学校
        logging.info(\'select school\')
        self.driver.find_element(*self.school_name).click()
        self.driver.find_elements(*self.forum_title)[1].click()
        self.driver.find_elements(*self.university)[1].click()

        #选择专业
        logging.info(\'select major\')
        self.driver.find_element(*self.perfectinfomation_major).click()
        self.driver.find_elements(*self.subject)[1].click()
        self.driver.find_elements(*self.group)[2].click()
        self.driver.find_elements(*self.search_item)[0].click()

        #注册
        self.driver.find_element(*self.perfectinfomation_goBtn).click()

    def check_registerStatus(self):
        logging.info(\'========check_registerStatus==========\')
        self.check_market_ad()

        try:
            self.driver.find_element(*self.button_mysefl).click()
            element = self.driver.find_element(*self.usercenter_username)
        except NoSuchElementException:
            logging.error(\'========register false=========\')
            self.get_screenshot(\'register fail\')
            return False
        else:
            logging.info(\'=========register success==========\')
            return True

if __name__ == \'__main__\':
    driver=appium_desired()
    r=RegisterVeiw(driver)
    username=\'zxw2000\'+\'fly\'+str(randint(1000,9999))
    password=\'zxw2000\'+str(randint(1000,9999))
    email=\'zxw2000\'+str(randint(1000,9999))+\'@163.com\'

    r.register_action(username,password,email)

4.common目录下存放着公共方法

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019-07-04 17:22
# @Author : zhouyang
# @File : commom_fun.py

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

class Commom(BaseView):
    cancelBtn=(By.ID,\'android:id/button2\')
    skipBtn=(By.ID,\'com.tal.kaoyan:id/tv_skip\')

    wemedia_cacel=(By.ID,\'com.tal.kaoyan:id/view_wemedia_cacel\')

    def check_cancleBtn(self):
        logging.info(\'===========check cancleBtn==========\')
        try:
            cancelBtn = self.driver.find_element(*self.cancelBtn)
        except NoSuchElementException:
            logging.info(\'no cancelBtn\')
        else:
            cancelBtn.click()

    def check_skipBtn(self):
        logging.info(\'===========check cancelBtn===========\')
        try:
            skipBtn = self.driver.find_element(*self.skipBtn)
        except NoSuchElementException:
            logging.info(\'no cancelBtn\')
        else:
            skipBtn.click()

    def get_size(self):
        x = driver.get_window_size()[\'width\']
        y = driver.get_window_size()[\'height\']
        return (x, y)

    def swipeLeft(self):
        l = self.get_size()
        x1 = int(l[0] * 0.9)
        x2 = int(l[0] * 0.1)
        y1 = int(l[1] * 0.5)
        driver.swipe(x1, y1, x2, y1, 1000)

    def getTime(self):
        self.now=time.strftime(\'%Y_%m_%d %H-%M-%S\')
        return self.now

    def get_screenshot(self,module):
        time=self.getTime()
        image_file=os.path.dirname(os.path.dirname(__file__))+\'/screenshot/%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========\')
            element.click()

    def get_csv_data(self,csv_file,line):
        logging.info(\'======get_csv_data========\')
        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




if __name__ == \'__main__\':
    driver=appium_desired()
    com=Commom(driver)
    com.check_cancleBtn()
    com.check_skipBtn()

    # def get_csv_data(csv_file,line):
    #     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
    #
    # csv_file=\'../data/account.csv\'
    # data=get_csv_data(csv_file,1)
    # print(data)

    # lists=[\'这\',\'是\',\'一个\',\'列表\']
    # for index,row in enumerate(lists):
    #     print(index,row)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019-07-03 11:05
# @Author : zhouyang
# @File : capability_yaml.py
\'\'\'
从desired_caps.yaml文件中获取capability数据,登录考研帮app,把日志保存在文件中
\'\'\'
from appium import webdriver
import yaml
import logging
import logging.config
import os


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

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

    desired_caps = {}
    desired_caps[\'platformName\'] = data[\'platformName\']
    desired_caps[\'platformVerion\'] = data[\'platformVersion\']
    desired_caps[\'deviceName\'] = data[\'deviceName\']
    #app使用相对路径
    base_dir = os.path.dirname(os.path.dirname(__file__))
    app_dir = os.path.join(base_dir, \'app\', data[\'appname\'])
    desired_caps[\'app\'] = app_dir

    desired_caps[\'noReset\'] = data[\'noReset\']
    desired_caps[\'appPackage\'] = data[\'appPackage\']
    desired_caps[\'appActivity\'] = data[\'appActivity\']
    desired_caps[\'unicodeKeyboard\'] = data[\'unicodeKeyboard\']
    desired_caps[\'resetKeyboard\'] = data[\'resetKeyboard\']

    logging.info(\'start info...\')

    driver = webdriver.Remote(\'http://\' + str(data[\'ip\']) + \':\' + str(data[\'port\']) + \'/wd/hub\', desired_caps)
    driver.implicitly_wait(8)
    return driver

if __name__ == \'__main__\':
    appium_desired()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019-07-05 16:18
# @Author : zhouyang
# @File : myunit.py

from common.desired_caps import appium_desired
import logging
import unittest
from time import sleep

class StartEnd(unittest.TestCase):
    def setUp(self):
        logging.info(\'===============setup==============\')
        self.driver=appium_desired()

    def tearDown(self):
        logging.info(\'=============teardown============\')
        sleep(5)
        self.driver.close_app()

5.config目录下存放所有配置文件,其中yaml文件中“:”后面一定要空一个格,否则会报错;.conf文件中内容,日志存放路径可以修改,日志表现形式等都可以修改

desired_caps.yaml

platformName: Android
platformVersion: 4.4.2
deviceName: 127.0.0.1:62001

#真机
#platformVersion: 4.4.2
#udid:
#deviceName: 127.0.0.1:62001
appname: kaoyan3.1.0.apk
appPackage: com.tal.kaoyan
appActivity: com.tal.kaoyan.ui.activity.SplashActivity
noReset: False
unicodeKeyboard: True
resetKeyboard: True
ip: 127.0.0.1
port: 4723

log.conf

[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.stdout,)

[handler_fileHandler]
class=FileHandler
level=INFO
formatter=form01
args=(\'../logs/runlog_conf.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

6.data目录中存放的是测试需要的数据,比如csv文件,Excel文件等

 

7.logs目录下存放测试过程中产生的日志,存放目录和日志名及日志内容均取决于log.conf文件中的 

args=(\’../logs/runlog_conf.log\’, \’a\’),a表示追加,否则第二次执行测试后产生的日志会覆盖

8.reports目录存放测试过程中产生的测试报告,测试报告的路径,名称,内容等都在run_test.py文件中定义

 

9.screenshot目录存放测试过程中的截图,路径,名称等都取决于common目录下的common_fun.py文件下的get_screenshot()方法

 

10.test_case目录下存放着所有的测试用例

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019-07-05 16:24
# @Author : zhouyang
# @File : test_login.py
\'\'\'
unittest写的测试用例
\'\'\'
import unittest
from common.myunit import StartEnd
from businessView.loginView import LoginView
import logging

class Test_Login(StartEnd):
    def test_login_zxw2018(self):
        logging.info(\'=========test_login_zxw2018=========\')
        l=LoginView(self.driver)
        l.login_action(\'自学网2018\',\'zxw2018\')
        self.assertTrue(l.check_loginStatus())

    def test_login_zxw2017(self):
        logging.info(\'=========test_login_zxw2017=========\')
        l=LoginView(self.driver)
        l.login_action(\'自学网2017\',\'zxw2017\')
        self.assertTrue(l.check_loginStatus())

    def test_login_error(self):
        logging.info(\'=========test_login_error=========\')
        l=LoginView(self.driver)
        l.login_action(\'123\',\'456\')
        self.assertTrue(l.check_loginStatus(),msg=\'login fail\')

if __name__ == \'__main__\':
    unittest.main()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019-07-22 16:32
# @Author : zhouyang
# @File : test_regiter.py
\'\'\'注册测试用例\'\'\'

from common.myunit import StartEnd
from businessView.register import RegisterVeiw
import logging
from random import randint
import unittest

class RegisterTest(StartEnd):

    def test_user_register(self):
        logging.info(\'=======start regiter========\')
        r = RegisterVeiw(self.driver)
        username = \'zxw2000\' + \'fly\' + str(randint(1000, 9999))
        password = \'zxw2000\' + str(randint(1000, 9999))
        email = \'zxw2000\' + str(randint(1000, 9999)) + \'@163.com\'

        self.assertTrue(r.register_action(username, password, email))

if __name__ == \'__main__\':
    unittest.main()

11.test_run目录下存放着run_test.py文件,用于执行测试,生成测试报告,也可以在里面添加发送邮件功能,生成的测试报告直接以邮件形式发送到邮箱

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2019-07-22 16:42
# @Author : zhouyang
# @File : run_test.py
\'\'\'执行测试用例,生成测试报告\'\'\'

import unittest
import logging
# from BSTestRunner import BSTestRunner
from HTMLTestRunner import HTMLTestRunner
import time

#指定测试用例和测试报告的路径
report_dir=\'../reports/\'
test_dir=\'../test_case\'

#加载测试用例
discover=unittest.defaultTestLoader.discover(test_dir,pattern=\'test_login.py\')

#定义报告的文件格式
now=time.strftime(\'%Y_%m_%d %H-%M-%S \')
report_name=report_dir+now+\'test_report.html\'

#运行用例并生成测试报告
with open(report_name,\'wb\') as f:
    runner=HTMLTestRunner(stream=f,title=u\'login test repotr\',description=u\'kyb login test report\')
    logging.info(\'start run testcasse......\')
    runner(discover)

 



版权声明:本文为xiuxiu123456原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/xiuxiu123456/p/11326113.html