当前位置:   article > 正文

csdn最详细最牛逼的 阿里最新app自动化测试---自动化测试框架搭建_app自动化测试框架爬数据

app自动化测试框架爬数据

目录

1.安装依赖以及项目的基本目录

2.pom解析

3. Excel数据驱动

4.测试报告

 5.优化conftest.py

 6. 多设备连接,并行执行测试代码


1.安装依赖以及项目的基本目录

# 安装依赖
pip install pytest      
pip install appium-python-client  
pip install openpyxl                     # excel文件处理
pip install pytest-html                  # 测试报告

2.pom解析

pom 设计的核心思想 就是将不同的页面单独进行维护,在做自动化的过程中,如果前端页面进行更改,原来写自动化代码就可能不再适用,因为前端页面更改了之后,元素定位已经不再适合,自动化用例执行失败。就要重新更改代码,比较麻烦。

pom 将页面与测试用例单独封装,页面上的每个操作都单独封装起来,测试用例只需要调用封装好的方法即可。如果页面有改动。只需要改页面中封装的操作即可。

下面以登录场景为例,编写自动化:

  1. conftest.py
  2. from appium import webdriver
  3. import pytest
  4. import os
  5. chromedriver= os.path.join(os.path.dirname(os.path.abspath(__file__)),'drivers/chrome/75.0.3770.140/chromedriver.exe')
  6. @pytest.fixture(scope='session')
  7. def driver():
  8. desired_caps = {
  9. 'platformName': 'Android', # 测试Android系统
  10. 'platformVersion': '7.1.2', # Android版本 可以在手机的设置中关于手机查看
  11. 'deviceName': '127.0.0.1:62001', # adb devices 命令查看 设置为自己的设备
  12. 'automationName': 'UiAutomator2', # 自动化引擎
  13. 'noReset': False, # 不要重置app的状态
  14. 'fullReset': False, # 不要清理app的缓存数据
  15. 'chromedriverExecutable': chromedriver, # chromedriver 对应的绝对路径
  16. 'appPackage': "org.cnodejs.android.md", # 应用的包名
  17. 'appActivity': ".ui.activity.LaunchActivity" # 应用的活动页名称(appium会启动app的加载页)
  18. }
  19. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_capabilities=desired_caps)
  20. driver.implicitly_wait(5) # 全局的隐式等待时间
  21. yield driver # 将driver 传递出来
  22. driver.quit()
  23. pom/basePage.py
  24. """
  25. 所有的页面都继承这个类,获得driver
  26. """
  27. import time
  28. from appium.webdriver.webdriver import WebDriver
  29. from selenium.common.exceptions import NoSuchElementException
  30. class BasePage:
  31. def __init__(self,driver:WebDriver):
  32. self.driver = driver
  33. # 获取toast的文本值
  34. @property
  35. def result_text(self):
  36. try:
  37. toast = self.driver.find_element_by_xpath('//android.widget.Toast')
  38. return toast.text
  39. except NoSuchElementException:
  40. return "找不到这个元素,请检查自己的自动化代码"
  41. pom/loginPage.py
  42. """
  43. 登陆页面
  44. """
  45. import time
  46. from appium.webdriver.webdriver import WebDriver
  47. from pom.basePage import BasePage
  48. class LoginPage(BasePage):
  49. # 初始化类的时候,打开登陆页面
  50. def __init__(self,driver:WebDriver):
  51. super(LoginPage,self).__init__(driver)
  52. # 判断是否是登陆页面
  53. current_activity = self.driver.current_activity
  54. if ".ui.activity.LoginActivity" in current_activity:
  55. pass
  56. else:
  57. # 不是登陆页面,则调用方法,打开登陆页面
  58. self.__go_login_page()
  59. # 导航到loginPage(登陆页面),定义一个私有的方法
  60. def __go_login_page(self):
  61. # 清空app的登陆状态(如果已经登陆,则去掉登陆状态)
  62. self.driver.reset()
  63. # 打开首页
  64. self.driver.start_activity(app_package='org.cnodejs.android.md',app_activity='.ui.activity.MainActivity')
  65. toggle_but = self.driver.find_element_by_android_uiautomator('resourceId("org.cnodejs.android.md:id/toolbar").childSelector(new UiSelector().className("android.widget.ImageButton"))')
  66. toggle_but.click()
  67. time.sleep(1)
  68. # 点击头像,去登陆页面
  69. avatar = self.driver.find_element_by_android_uiautomator('text("点击头像登录").resourceId("org.cnodejs.android.md:id/tv_login_name")')
  70. avatar.click()
  71. # 使用token的方式进行登录
  72. def with_token_login(self,token):
  73. self.driver.find_element_by_id('org.cnodejs.android.md:id/edt_access_token').send_keys(token)
  74. loginbtn = self.driver.find_element_by_android_uiautomator('text("登录").resourceId("org.cnodejs.android.md:id/btn_login")')
  75. # 点击登陆
  76. loginbtn.click()
  77. # 登陆失败的断言
  78. @property
  79. def with_token_failed_text(self):
  80. # 1. 截图
  81. ele = self.driver.find_element_by_id('org.cnodejs.android.md:id/edt_access_token')
  82. png = ele.screenshot_as_base64
  83. # 2. TODO 调用 ocr 图片识别 将图片中文字识别出来
  84. return ""
  85. # 扫码登陆
  86. def with_code_login(self):
  87. pass
  88. # 使用github登陆
  89. def with_github_login(self):
  90. pass
  91. testcases/test_user.py
  92. from pom.loginPage import LoginPage
  93. # 登陆的测试用例
  94. # 使用conftest.py 中定义的 driver
  95. def test_login(driver):
  96. # 打开登录页面
  97. loginpage = LoginPage(driver)
  98. # 使用token进行登录
  99. loginpage.with_token_login('d1563473-1f0d-4307-9774-6c2ff49c93ab')
  100. # 登陆成功,验证totas文本值
  101. result = loginpage.result_text
  102. assert result == "登录成功"

启动appium , 执行   pytest testcases\test_user.py -s -v  ,查看运行结果:

(登陆成功)

 (登陆失败)

下面以登录后发帖场景为例,编写自动化:

  1. pom/homePage.py
  2. """
  3. 首页
  4. """
  5. from pom.basePage import BasePage
  6. from pom.createTopicPage import CreateTopicPage
  7. class HomePage(BasePage):
  8. def __init__(self,driver):
  9. super(HomePage,self).__init__(driver)
  10. # 判断一下,是否是首页
  11. if '.ui.activity.MainActivity' in self.driver.current_activity:
  12. pass
  13. else:
  14. self.__go_home_page()
  15. # 打开首页
  16. def __go_home_page(self):
  17. self.driver.start_activity(app_activity='.ui.activity.LaunchActivity')
  18. # 去发帖页面
  19. def go_create_topic(self):
  20. # 判断是否已经到达创建话题页面
  21. while not '.ui.activity.CreateTopicActivity' in self.driver.current_activity:
  22. # 再重新点击一下
  23. create_btn = self.driver.find_element_by_android_uiautomator(
  24. '.resourceId("org.cnodejs.android.md:id/fab_create_topic")')
  25. create_btn.click()
  26. return CreateTopicPage(self.driver)
  27. pom/createTopicPage.py
  28. """
  29. 发帖页面
  30. """
  31. from pom.basePage import BasePage
  32. class CreateTopicPage(BasePage):
  33. # 发布话题
  34. def create_new_topic(self,tab,title,content):
  35. # 选择类型
  36. spinner = self.driver.find_element_by_android_uiautomator('.resourceId("org.cnodejs.android.md:id/spn_tab")')
  37. spinner.click()
  38. tab_selcotor = f'.resourceId("android:id/text1").text("{tab}")'
  39. self.driver.find_element_by_android_uiautomator(tab_selcotor).click()
  40. # 输入标题
  41. title_content = self.driver.find_element_by_android_uiautomator(
  42. 'resourceId("org.cnodejs.android.md:id/edt_title")')
  43. title_content.send_keys(title)
  44. # 输入内容
  45. content_area = self.driver.find_element_by_android_uiautomator(
  46. 'resourceId("org.cnodejs.android.md:id/edt_content")')
  47. content_area.send_keys(content)
  48. # 点击发送
  49. send_btn = self.driver.find_element_by_android_uiautomator(
  50. 'resourceId("org.cnodejs.android.md:id/action_send")')
  51. send_btn.click()
  52. testcases/test_topics.py
  53. from pom.homePage import HomePage
  54. from pom.loginPage import LoginPage
  55. # 发帖的测试用例
  56. def test_create_topic(driver):
  57. loginpage = LoginPage(driver)
  58. # 用户登录成功
  59. loginpage.with_token_login('d1563473-1f0d-4307-9774-6c2ff49c93ab')
  60. # 首页打开
  61. hp = HomePage(driver)
  62. # 进入创建话题页面
  63. create_page = hp.go_create_topic()
  64. create_page.create_new_topic(tab='分享',title='123',content='哈哈哈哈哈哈')
  65. result = create_page.result_text
  66. # 根据发帖结果做断言
  67. assert result == "标题要求10字以上"
 

启动appium , 执行   pytest testcases\test_topics.py -s -v  ,查看运行结果:

也可以执行 pytest,查看登陆,和发帖2个测试用例的执行结果:

3. Excel数据驱动

testdata/data.xlsx

  1. utils/file_handler.py
  2. """
  3. 登陆测试用例的数据驱动化测试
  4. """
  5. import pytest
  6. from pom.loginPage import LoginPage
  7. from utils.file_handler import FileHandler
  8. fl = FileHandler()
  9. # 从Excel文件中获取数据
  10. data = fl.get_data_by_sheet('用户登录')
  11. class TestDdtLogin:
  12. @pytest.mark.parametrize('token,status,expect_val',data)
  13. def test_login(self,driver,token,status,expect_val):
  14. # 打开登录页面
  15. loginpage = LoginPage(driver)
  16. # 使用token进行登录
  17. loginpage.with_token_login(token)
  18. if status == '成功':
  19. # 登录成功, 验证toast的文本值为登录成功
  20. result = loginpage.result_text
  21. assert result == expect_val
  22. if status == "失败":
  23. result = loginpage.with_token_failed_text
  24. assert result == expect_val
  25. testcases/test_ddt/test_ddt_login.py
  26. """
  27. 登陆测试用例的数据驱动化测试
  28. """
  29. import pytest
  30. from pom.loginPage import LoginPage
  31. from utils.file_handler import FileHandler
  32. fl = FileHandler()
  33. # 从Excel文件中获取数据
  34. data = fl.get_data_by_sheet('用户登录')
  35. class TestDdtLogin:
  36. @pytest.mark.parametrize('token,status,expect_val',data)
  37. def test_login(self,driver,token,status,expect_val):
  38. # 打开登录页面
  39. loginpage = LoginPage(driver)
  40. # 使用token进行登录
  41. loginpage.with_token_login(token)
  42. if status == '成功':
  43. # 登录成功, 验证toast的文本值为登录成功
  44. result = loginpage.result_text
  45. assert result == expect_val
  46. if status == "失败":
  47. result = loginpage.with_token_failed_text
  48. assert result == expect_val
 

启动appium , 执行   pytest testcases\test_ddt\test_ddt_login.py -s -v  ,查看运行结果:

4.测试报告

pytest-html pytest-html · PyPI

pytest-allure allure-pytest · PyPI

测试报告一:pytest-html

  1. main.py
  2. """
  3. 项目运行文件,并添加测试报告
  4. """
  5. import pytest
  6. import os,time
  7. if __name__ == '__main__':
  8. report_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),'reports')
  9. if not os.path.exists(report_dir):
  10. os.mkdir(report_dir)
  11. report = time.strftime('%Y_%m_%d_%H_%M_%S')
  12. reportfile = os.path.join(report_dir,report+'.html')
  13. pytest.main(['testcases','-s','-v',f'--html={reportfile}'])
 

运行main.py 文件,Run main.py 执行即可,会执行 testcases 里面所有的测试用例

执行结束之后,生成的测试报告,我们可以在浏览器中打开

 5.优化conftest.py

   增加  每个测试用例执行完成之后,如果执行失败截图,截图的名称为测试用例名称+时间格式  的相关处理

  1. from appium import webdriver
  2. import pytest
  3. import os, time
  4. chromedriver= os.path.join(os.path.dirname(os.path.abspath(__file__)),'drivers/chrome/75.0.3770.140/chromedriver.exe')
  5. # scope='session' 标记的方法执行域为---->所有测试用例运行之前/之后 运行的方法
  6. @pytest.fixture(scope='session',autouse=True)
  7. def driver():
  8. desired_caps = {
  9. 'platformName': 'Android', # 测试Android系统
  10. 'platformVersion': '7.1.2', # Android版本 可以在手机的设置中关于手机查看
  11. 'deviceName': '127.0.0.1:62001', # adb devices 命令查看 设置为自己的设备
  12. 'automationName': 'UiAutomator2', # 自动化引擎
  13. 'noReset': False, # 不要重置app的状态
  14. 'fullReset': False, # 不要清理app的缓存数据
  15. 'chromedriverExecutable': chromedriver, # chromedriver 对应的绝对路径
  16. 'appPackage': "org.cnodejs.android.md", # 应用的包名
  17. 'appActivity': ".ui.activity.LaunchActivity" # 应用的活动页名称(appium会启动app的加载页)
  18. }
  19. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_capabilities=desired_caps)
  20. driver.implicitly_wait(5) # 全局的隐式等待时间
  21. yield driver # 将driver 传递出来
  22. driver.quit()
  23. # 该方法是用来获取测试用例执行的结果(passed / FAILED)
  24. @pytest.hookimpl(tryfirst=True,hookwrapper=True)
  25. def pytest_runtest_makereport(item, call):
  26. outcome = yield
  27. rep = outcome.get_result() # 获取用例的执行结果
  28. print('用例的执行结果rep---->',rep)
  29. setattr(item, "rep_" + rep.when, rep) # 将执行结果保存到 item 属性中 , req.when 执行时
  30. # scope='function' 标记的方法执行域为---->每个测试用例运行之前/之后 运行的方法
  31. @pytest.fixture(scope='function',autouse=True)
  32. def case_run(driver:webdriver,request): # request 为 pytest_runtest_makereport 方法获取到的执行结果(固定参数和用法)
  33. yield
  34. # 每个测试用例执行完成之后,如果执行失败截图,截图的名称为测试用例名称+时间格式
  35. if request.node.rep_call.failed:
  36. screenshots = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'screenshots')
  37. if not os.path.exists(screenshots):
  38. os.mkdir(screenshots)
  39. casename: str = request.node.nodeid
  40. # print("执行测试用例的名字:", casename)
  41. # 测试用例的名字很长 testcases/test_ddt/test_ddt_login.py::TestDdtLogin::test_login[....]
  42. # 对字符串进行截取,截取之后显示为 test_ddt_login-TestDdtLogin
  43. casename = casename[casename.rfind('/')+1:casename.rfind('::')].replace('.py::','-')
  44. filename = casename + '-' + time.strftime('%Y_%m_%d-%H_%M_%S') +".png"
  45. screenshot_file = os.path.join(screenshots, filename)
  46. # 保存截图
  47. driver.save_screenshot(screenshot_file)

 6. 多设备连接,并行执行测试代码

   通过代码的方式自动的获取连接的多个设备,拿到设备的串号,启动多个appium,通过多进程的方式,在多个设备上并行的执行自动化测试用例

     点击查看优化后的代码

最后,执行 pip freeze > requirements.txt   ,将项目中使用的第三方包的包名和版本导出到文件中

                   pip install -r requirements.txt    # 安装requirements.txt文件夹中库及对应版本

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/533706
推荐阅读
相关标签
  

闽ICP备14008679号