项目作者: lucas3414

项目描述 :
这是一个关于python的WebUI自动化测试的项目,之前用的是unittest测试框架,现在改成pytest测试框架,Python+PageObject+Pytest
高级语言: Python
项目地址: git://github.com/lucas3414/python_web_framework.git


python_web_framework

这是一个关于python的WebUI自动化测试的项目,之前用的是unittest测试框架,现在改成pytest测试框架,Python+PageObject+Pytest

实现页面元素、页面对象及业务、测试数据分离

项目结构:说明

  1. .
  2. |-- assets
  3. | `-- style.css
  4. |-- cases --------------------- 测试用例模块
  5. | |-- conftest.py
  6. | |-- __init__.py
  7. | |-- logincases --------------------- 测试模块1
  8. | | |-- conftest.py
  9. | | |-- __init__.py
  10. | | `-- test_login.py
  11. | `-- usercases --------------------- 测试模块2
  12. | |-- conftest.py
  13. | |-- __init__.py
  14. | `-- test_user_add.py
  15. |-- Common --------------------- 配置和功能函数
  16. | |-- config
  17. | | `-- config.ini --------------------- 配置文件, 日志、报告、截图的目录等
  18. | |-- __init__.py
  19. | |-- plugs --------------------- 功能函数
  20. | | |-- basepage.py --------------------- 封装的 webdriver Api (后续可以自己添加,目前只是封装的少许)
  21. | | |-- get_config.py --------------------- 获取配置文件方法
  22. | | |-- get_log.py --------------------- 日志的配置方法
  23. | | |-- __init__.py
  24. |-- Locators --------------------- 测试页面定位
  25. | |-- __init__.py
  26. | |-- LoginLocators --------------------- 登录模块的页面对象定位
  27. | | |-- __init__.py
  28. | | |-- login_locators.py
  29. | `-- UserLocators --------------------- 用户模块的页面对象定位
  30. | |-- __init__.py
  31. | `-- user_locators.py
  32. |-- OutPuts --------------------- 输出
  33. | |-- image --------------------- 截图
  34. | |-- log --------------------- 日志
  35. | `-- reports --------------------- 报告
  36. | `-- report.html
  37. |-- PageObjects ---------------------- 业务流程
  38. | |-- IndexPage ---------------------- 主页模块的页面对象
  39. | | |-- index_page.py
  40. | | |-- __init__.py
  41. | |-- __init__.py
  42. | |-- LoginPage ---------------------- 登录模块的页面对象
  43. | | |-- __init__.py
  44. | | |-- login_page.py
  45. | `-- UserPage ---------------------- 用户模块的页面对象
  46. | |-- __init__.py
  47. | `-- user_page.py
  48. |-- README.md
  49. `-- TestDatas ---------------------- 测试数据
  50. |-- GobalDatas ---------------------- 全局的测试数据
  51. | |-- gobal_datas.py
  52. | |-- __init__.py
  53. |-- __init__.py
  54. |-- LoginDatas ---------------------- 登录模块的正常、异常测试数据
  55. | |-- __init__.py
  56. | |-- login_datas.py
  57. `-- UserDatas ---------------------- 用户模块的正常、异常测试数据
  58. |-- __init__.py
  59. `-- user_add_datas.py

以下是简单说明:

  1. case: pytest的参数化 fixture的使用 conftest全局和本地的配置
  2. Cases/conftest:测试类的前置和后置,单个测试用例的前置和后置
  3. @pytest.fixture(scope='session')
  4. def project_session_start():
  5. logger.info("==========开始 XX项目 执行测试===========")
  6. global driver
  7. driver = webdriver.Chrome()
  8. driver.maximize_window()
  9. yield driver
  10. driver.quit()
  11. logger.info("==========结束 XX项目 测试===========")
  12. @pytest.fixture(scope='module')
  13. def project_module_start():
  14. logger.info("==========开始 XX模块 执行测试===========")
  15. global driver
  16. driver = webdriver.Chrome()
  17. driver.maximize_window()
  18. yield driver
  19. driver.quit()
  20. logger.info("==========结束 XX模块 测试===========")

——————————————————————————————————————————————————————————————————-

测试用例:参数的正常和异常用例

  1. pytest.mark.usefixtures('start_session')
  2. @pytest.mark.usefixtures('refresh_page')
  3. class TestUserAdd:
  4. @pytest.mark.smoke
  5. def test_add_user(self, start_session):
  6. logger.info(" 执行 {0} 测试用例 ".format(sys._getframe().f_code.co_name))
  7. logger.info('正常新增用户测试用例')
  8. start_session[1].add_user(UAD.success_data['username'], UAD.success_data['password'],
  9. UAD.success_data['email'],
  10. UAD.success_data['phone'])
  11. logger.info("期望值:{0}".format(UAD.success_data['Msg']))
  12. logger.info("实际值:{0}".format(start_session[1].get_add_result_msg()))
  13. try:
  14. assert start_session[1].get_add_result_msg() == UAD.success_data['Msg']
  15. logger.info(" 结束执行 {0} 测试用例, 测试结果 --- PASS ".format(sys._getframe().f_code.co_name))
  16. start_session[1].save_pictuer("{0}-正常截图".format(UAD.success_data['name']))
  17. except:
  18. logger.info(" 结束执行 {0} 测试用例, 测试结果 --- False ".format(sys._getframe().f_code.co_name))
  19. start_session[1].save_pictuer("{0}-异常截图".format(UAD.success_data['name']))
  20. raise
  21. @pytest.mark.parametrize('data', UAD.error_usernameFormat_data)
  22. def test_add_usernameFormat_error(self, data, start_session):
  23. print(" 执行 {0} 测试用例 ".format(sys._getframe().f_code.co_name))
  24. logger.info(" 异常测试用例:{0} ".format(data['name']))
  25. start_session[1].add_user(data['username'], data['password'], data['email'], data['phone'])
  26. logger.info("期望值:{0}".format(data['Msg']))
  27. logger.info("实际值:{0}".format(start_session[1].get_add_result_msg()))
  28. try:
  29. assert start_session[1].get_add_result_msg() == data['Msg']
  30. logger.info(" 结束执行 {0} 测试用例, 测试结果 --- PASS ".format(sys._getframe().f_code.co_name))
  31. start_session[1].save_pictuer("{0}-正常截图".format(data['name']))
  32. except:
  33. logger.info(" 结束执行 {0} 测试用例, 测试结果 --- False ".format(sys._getframe().f_code.co_name))
  34. start_session[1].save_pictuer("{0}-异常截图".format(data['name']))
  35. raise
  36. @pytest.mark.parametrize('data', UAD.error_usernameFormat_data)
  37. def test_add_passwordFormat_error(self, data, start_session):
  38. logger.info(" 执行 {0} 测试用例 ".format(sys._getframe().f_code.co_name))
  39. logger.info(" 异常测试用例:{0} ".format(data['name']))
  40. start_session[1].add_user(data['username'], data['password'], data['email'], data['phone'])
  41. logger.info("期望值:{0}".format(data['Msg']))
  42. logger.info("实际值:{0}".format(start_session[1].get_add_result_msg()))
  43. try:
  44. assert start_session[1].get_add_result_msg() == data['Msg']
  45. logger.info(" 结束执行 {0} 测试用例, 测试结果 --- PASS ".format(sys._getframe().f_code.co_name))
  46. start_session[1].save_pictuer("{0}-正常截图".format(data['name']))
  47. except:
  48. logger.info(" 结束执行 {0} 测试用例, 测试结果 --- False ".format(sys._getframe().f_code.co_name))
  49. start_session[1].save_pictuer("{0}-异常截图".format(data['name']))
  50. raise

——————————————————————————————————————————————————————————————————-

Locators:

  1. #页面的元素
  2. class LoginLocator:
  3. username_loc = (By.XPATH, '//*[@id="app"]/div/form/div[1]/div/div/input')
  4. password_loc = (By.XPATH, '//*[@id="app"]/div/form/div[2]/div/div/input')
  5. login_btn_loc = (By.XPATH, '//*[@type="button"]')
  6. error_msg_loc = (By.CLASS_NAME, 'el-message__content')

——————————————————————————————————————————————————————————————————-

PageObjects:

  1. # 业务功能流程
  2. class LoginPage(BasePage):
  3. # 登录
  4. def login(self, username, password):
  5. doc = '登录页面_登录功能_查找元素失败'
  6. self.input_element(loc.username_loc, username, doc)
  7. self.input_element(loc.password_loc, password, doc)
  8. self.click_element(loc.login_btn_loc, doc)
  9. # 获取错误提示
  10. def get_login_errMsg(self):
  11. doc = '登录页面_登录功能错误信息_查找元素失败'
  12. # self.wait_eleVisible(loc.error_msg_loc)
  13. return self.get_element_text(loc.error_msg_loc, doc)

——————————————————————————————————————————————————————————————————-

TestDatas

  1. # 测试数据
  2. # 正常场景测试数据
  3. success_data = {'name': '登录功能-正常测试', 'username': 'admin', 'password': '123456'}
  4. # 异常场景测试 - username
  5. error_usernameFormat_data = [
  6. {'name': '登录功能-异常测试-用户名为空', 'username': '', 'password': '123456', 'errorMsg': '参数错误'},
  7. {'name': '登录功能-异常测试-用户名不存在', 'username': 'xxoo', 'password': '123456', 'errorMsg': '用户名不存在'},
  8. ]
  9. # 异常场景测试 - password
  10. error_passwordFormat_data = [
  11. {'name': '登录功能-异常测试-密码为空', 'username': 'admin', 'password': '', 'errorMsg': '参数错误'},
  12. {'name': '登录功能-异常测试-密码错误', 'username': 'admin', 'password': '1234567', 'errorMsg': '密码错误'},
  13. ]

——————————————————————————————————————————————————————————————————-