• Appium+Pytest+Allure实现APP自动化测试,小试牛刀


    Hi,大家好。Appium结合Pytest开展App自动化测试时,你知道如何自动运行用例并发执行吗?费话不多说,直接上代码, 毕竟想让每个人都能看明白也不容易,所以附上代码,有兴趣的自行研究,如需获取框架源码可以在ITester软件测试公众号后台回复“APP框架”。

    一、项目介绍

    1、项目环境

    项目环境如下:

    • Python
    • pytest
    • allure
    • appium
    • node
    • 夜神模拟器

    2、项目环境

    项目结构截图如下所示:

    项目结构说明:

    • base:存放基本的方法;
    • cases:存放测试用例;
    • common:一些公共的方法;
    • config:存放配置文件;
    • log:日志文件;
    • image:存放测试截图;
    • Page:测试的定位元素;
    • report:测试报告;
    • pytest.ini:pytest启动配置文件;
    • requirements.txt:需要安装的py模块;
    • run.py:运行文件。

    二、项目实现

    1、base_page.py
    base/base_page.py:封装一些方法,元素的点击、输入、查找,还有一些自己需要的公共方法也封装在此。

     

    2、check_port.py

    common/check_port.py:检测端口是否被占用,如被占用则释放。

    1. #!/usr/bin/python3
    2. # -*- coding:utf-8 -*-
    3. # @Software:PyCharm
    4. # @File : check_port.py
    5. import socket
    6. import os
    7. def check_port(host, port):
    8. """检测指定的端口是否被占用"""
    9. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建socket对象
    10. try:
    11. s.connect((host, port))
    12. s.shutdown(2)
    13. except OSError:
    14. print('port %s is available! ' % port)
    15. return True
    16. else:
    17. print('port %s already be in use !' % port)
    18. return False
    19. def release_port(port):
    20. """释放指定的端口"""
    21. cmd_find = 'netstat -aon | findstr {}'.format(port) # 查找对应端口的pid
    22. print(cmd_find)
    23. # 返回命令执行后的结果
    24. result = os.popen(cmd_find).read()
    25. print(result)
    26. if str(port) and 'LISTENING' in result:
    27. # 获取端口对应的pid进程
    28. i = result.index('LISTENING')
    29. start = i + len('LISTENING') + 7
    30. end = result.index('\n')
    31. pid = result[start:end]
    32. cmd_kill = 'taskkill -f -pid %s' % pid # 关闭被占用端口的pid
    33. print(cmd_kill)
    34. os.popen(cmd_kill)
    35. else:
    36. print('port %s is available !' % port)
    37. if __name__ == '__main__':
    38. host = '127.0.0.1'
    39. port = 4723
    40. if not check_port(host, port):
    41. print("端口被占用")
    42. release_port(port)

    3、get_main_js.py

    common/get_main_js.py:获取main.js,使用main.js启动appium server。

    1. #!/usr/bin/python3
    2. # -*- coding:utf-8 -*-
    3. # @Software:PyCharm
    4. # @File : get_main_js.py
    5. import subprocess
    6. from config.root_config import LOG_DIR
    7. """
    8. 获取main.js的位置,使用main.js启动appium server
    9. """
    10. class MainJs(object):
    11. """获取启动appium服务的main.js命令"""
    12. def __init__(self, cmd: str = "where main.js"):
    13. self.cmd = cmd
    14. def get_cmd_result(self):
    15. p = subprocess.Popen(self.cmd,
    16. stdin=subprocess.PIPE,
    17. stdout=subprocess.PIPE,
    18. stderr=subprocess.PIPE,
    19. shell=True)
    20. with open(LOG_DIR + "/" + "cmd.txt", "w", encoding="utf-8") as f:
    21. f.write(p.stdout.read().decode("gbk"))
    22. with open(LOG_DIR + "/" + "cmd.txt", "r", encoding="utf-8") as f:
    23. cmd_result = f.read().strip("\n")
    24. return cmd_result
    25. if __name__ == '__main__':
    26. main = MainJs("where main.js")
    27. print(main.get_cmd_result())

    4、desired_caps.yaml

    config/desired_caps.yml:app自动化测试项目相关的yaml。

    5、root_config.py

    config/root_config.py:项目文件和路径配置信息。

    6、conftest.py

    conftest.py:

    1. #!/usr/bin/python3
    2. # -*- coding:utf-8 -*-
    3. # @Software:PyCharm
    4. # @File : root_config.py
    5. from drivers.app_driver import BaseDriver
    6. import pytest
    7. import time
    8. from common.check_port import release_port
    9. base_driver = None
    10. def pytest_addoption(parser):
    11. parser.addoption("--cmdopt", action="store", default="device_info", help=None)
    12. @pytest.fixture(scope="session")
    13. def cmd_opt(request):
    14. return request.config.getoption("--cmdopt")
    15. @pytest.fixture(scope="session")
    16. def common_driver(cmd_opt):
    17. cmd_opt = eval(cmd_opt)
    18. print("cmd_opt", cmd_opt)
    19. global base_driver
    20. base_driver = BaseDriver(cmd_opt)
    21. time.sleep(1)
    22. driver = base_driver.get_base_driver()
    23. yield driver
    24. # driver.close_app()
    25. driver.quit()
    26. release_port(cmd_opt["server_port"])

    7、test_concurrent.py

    cases/test_concurrent.py:绘制密码并解锁。

    1. #!/usr/bin/python3
    2. # -*- coding:utf-8 -*-
    3. # @Software:PyCharm
    4. # @File : test_concurrent.py
    5. import pytest
    6. import time
    7. from appium.webdriver.common.mobileby import MobileBy
    8. from base.base_page import Base
    9. class TestGesture(object):
    10. def test_gesture_password(self, common_driver):
    11. """简单的做了一个绘制手势密码的过程"""
    12. driver = common_driver
    13. base = Base(driver)
    14. base.skip_welcome_page('left', 3) # 滑动屏幕
    15. time.sleep(3) # 为了看滑屏的效果
    16. driver.start_activity(app_package="com.xxzb.fenwoo",
    17. app_activity=".activity.user.CreateGesturePwdActivity")
    18. commit_btn = (MobileBy.ID, 'com.xxzb.fenwoo:id/right_btn')
    19. password_gesture = (MobileBy.ID, 'com.xxzb.fenwoo:id/gesturepwd_create_lockview')
    20. element_commit = base.find_element(commit_btn)
    21. element_commit.click()
    22. password_element = base.find_element(password_gesture)
    23. base.gesture_password(password_element, 1, 2, 3, 6, 5, 4, 7, 8, 9)
    24. time.sleep(5) # 看效果
    25. if __name__ == '__main__':
    26. pytest.main()

    8、run_case.py

    run_case.py:运行文件。

    1. #!/usr/bin/python3
    2. # -*- coding:utf-8 -*-
    3. # @Software:PyCharm
    4. # @File : run_case.py
    5. import pytest
    6. import os
    7. from multiprocessing import Pool
    8. device_infos = [
    9. {
    10. "platform_version": "5.1.1",
    11. "server_port": "4723",
    12. "device_port": "62001",
    13. },
    14. {
    15. "platform_version": "5.1.1",
    16. "server_port": "4725",
    17. "device_port": "62025",
    18. }
    19. ]
    20. def main(device_info):
    21. pytest.main(["--cmdopt={}".format(device_info),
    22. "--alluredir", "./allure-results", "-vs"])
    23. os.system("allure generate allure-results -o allure-report --clean")
    24. if __name__ == "__main__":
    25. with Pool(2) as pool:
    26. pool.map(main, device_infos)
    27. pool.close()
    28. pool.join()

    三、项目总结

    1、项目效果

    如下所示,最终实现启动APP,绘制解锁图案,进入APP主页。

    2、项目思路

    Pytest作为单元测试框架,要完成App测试自动化需要把Pytest和Appium进行整合,同时利用Allure完成测试报告的产出。编写App自动化测试的步骤如下:

    1)设计待测试APP的自动化测试用例;

    2)新建app测试项目;

    3)配置conftestpy文件等;

    4)编写整体app测试用例运行文件;

    5)将设计好的自动化测试用例转化成脚本;

    3、项目小结

    上述只是初步实现了一个多手机并发的需求,希望项目更加的规范还需要引入PO设计模式,其次base_page.py中还可以封装更多的方法,上述代码中也只封装了几个方法,如果真正的把这个并发引入到项目中肯定还需要完善,感兴趣的小伙伴可以试试。

    最后我也整理了一些软件测试学习资料,对于学软件测试的小伙伴来说应该会很有帮助,为了更好地整理每个模块

    需要的私信我关键字【555】免费获取哦 注意关键字是:555

    全套软件测试自动化测试教学视频

    300G教程资料下载【视频教程+PPT+项目源码】

    全套软件测试自动化测试大厂面经

     

  • 相关阅读:
    【根据车间号[81321000]未找到ERP逻辑仓】
    Django常见面试题总结(二)
    从入门到进阶 之 ElasticSearch 文档、分词器 进阶篇
    小编闲谈——刷题网站
    Rust调用同级目录中的rs文件和调用下级目录中的rs文件
    ASCII纯文本绘制流程图
    Win11杜比全景声无法正常运行的解决方法教学
    你有对象类,我有结构体,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang结构体(struct)的使用EP06
    react父子组件通信?
    docker 安装mysql 5.7
  • 原文地址:https://blog.csdn.net/caixiangting/article/details/125627985