Hi,大家好。Appium结合Pytest开展App自动化测试时,你知道如何自动运行用例并发执行吗?费话不多说,直接上代码, 毕竟想让每个人都能看明白也不容易,所以附上代码,有兴趣的自行研究,如需获取框架源码可以在ITester软件测试公众号后台回复“APP框架”。
1、项目环境
项目环境如下:
2、项目环境
项目结构截图如下所示:
项目结构说明:
1、base_page.py
base/base_page.py:封装一些方法,元素的点击、输入、查找,还有一些自己需要的公共方法也封装在此。
2、check_port.py
common/check_port.py:检测端口是否被占用,如被占用则释放。
- #!/usr/bin/python3
- # -*- coding:utf-8 -*-
- # @Software:PyCharm
- # @File : check_port.py
-
- import socket
- import os
-
- def check_port(host, port):
- """检测指定的端口是否被占用"""
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建socket对象
- try:
- s.connect((host, port))
- s.shutdown(2)
- except OSError:
- print('port %s is available! ' % port)
- return True
- else:
- print('port %s already be in use !' % port)
- return False
-
-
- def release_port(port):
- """释放指定的端口"""
- cmd_find = 'netstat -aon | findstr {}'.format(port) # 查找对应端口的pid
- print(cmd_find)
-
- # 返回命令执行后的结果
- result = os.popen(cmd_find).read()
- print(result)
-
- if str(port) and 'LISTENING' in result:
- # 获取端口对应的pid进程
- i = result.index('LISTENING')
- start = i + len('LISTENING') + 7
- end = result.index('\n')
- pid = result[start:end]
- cmd_kill = 'taskkill -f -pid %s' % pid # 关闭被占用端口的pid
- print(cmd_kill)
- os.popen(cmd_kill)
- else:
- print('port %s is available !' % port)
-
- if __name__ == '__main__':
- host = '127.0.0.1'
- port = 4723
- if not check_port(host, port):
- print("端口被占用")
- release_port(port)
3、get_main_js.py
common/get_main_js.py:获取main.js,使用main.js启动appium server。
- #!/usr/bin/python3
- # -*- coding:utf-8 -*-
- # @Software:PyCharm
- # @File : get_main_js.py
-
- import subprocess
- from config.root_config import LOG_DIR
-
- """
- 获取main.js的位置,使用main.js启动appium server
- """
-
- class MainJs(object):
- """获取启动appium服务的main.js命令"""
-
- def __init__(self, cmd: str = "where main.js"):
- self.cmd = cmd
-
- def get_cmd_result(self):
- p = subprocess.Popen(self.cmd,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- shell=True)
- with open(LOG_DIR + "/" + "cmd.txt", "w", encoding="utf-8") as f:
- f.write(p.stdout.read().decode("gbk"))
- with open(LOG_DIR + "/" + "cmd.txt", "r", encoding="utf-8") as f:
- cmd_result = f.read().strip("\n")
- return cmd_result
-
- if __name__ == '__main__':
- main = MainJs("where main.js")
- 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:
- #!/usr/bin/python3
- # -*- coding:utf-8 -*-
- # @Software:PyCharm
- # @File : root_config.py
-
- from drivers.app_driver import BaseDriver
- import pytest
- import time
-
- from common.check_port import release_port
- base_driver = None
-
- def pytest_addoption(parser):
- parser.addoption("--cmdopt", action="store", default="device_info", help=None)
-
- @pytest.fixture(scope="session")
- def cmd_opt(request):
- return request.config.getoption("--cmdopt")
-
- @pytest.fixture(scope="session")
- def common_driver(cmd_opt):
- cmd_opt = eval(cmd_opt)
- print("cmd_opt", cmd_opt)
- global base_driver
- base_driver = BaseDriver(cmd_opt)
- time.sleep(1)
- driver = base_driver.get_base_driver()
- yield driver
- # driver.close_app()
- driver.quit()
- release_port(cmd_opt["server_port"])
7、test_concurrent.py
cases/test_concurrent.py:绘制密码并解锁。
- #!/usr/bin/python3
- # -*- coding:utf-8 -*-
- # @Software:PyCharm
- # @File : test_concurrent.py
-
- import pytest
- import time
- from appium.webdriver.common.mobileby import MobileBy
- from base.base_page import Base
-
- class TestGesture(object):
- def test_gesture_password(self, common_driver):
- """简单的做了一个绘制手势密码的过程"""
- driver = common_driver
- base = Base(driver)
- base.skip_welcome_page('left', 3) # 滑动屏幕
- time.sleep(3) # 为了看滑屏的效果
- driver.start_activity(app_package="com.xxzb.fenwoo",
- app_activity=".activity.user.CreateGesturePwdActivity")
- commit_btn = (MobileBy.ID, 'com.xxzb.fenwoo:id/right_btn')
- password_gesture = (MobileBy.ID, 'com.xxzb.fenwoo:id/gesturepwd_create_lockview')
- element_commit = base.find_element(commit_btn)
- element_commit.click()
- password_element = base.find_element(password_gesture)
- base.gesture_password(password_element, 1, 2, 3, 6, 5, 4, 7, 8, 9)
- time.sleep(5) # 看效果
-
- if __name__ == '__main__':
- pytest.main()
8、run_case.py
run_case.py:运行文件。
- #!/usr/bin/python3
- # -*- coding:utf-8 -*-
- # @Software:PyCharm
- # @File : run_case.py
-
- import pytest
- import os
- from multiprocessing import Pool
-
- device_infos = [
- {
- "platform_version": "5.1.1",
- "server_port": "4723",
- "device_port": "62001",
- },
- {
- "platform_version": "5.1.1",
- "server_port": "4725",
- "device_port": "62025",
- }
- ]
-
- def main(device_info):
- pytest.main(["--cmdopt={}".format(device_info),
- "--alluredir", "./allure-results", "-vs"])
- os.system("allure generate allure-results -o allure-report --clean")
-
- if __name__ == "__main__":
- with Pool(2) as pool:
- pool.map(main, device_infos)
- pool.close()
- 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+项目源码】
全套软件测试自动化测试大厂面经