之前在做手机app 自动化的时候,每次在自动化测试脚本运行之前,需要手动启动appium 服务器,
image.png
在开发环境中这样做没有什么问题,但是在服务器端执行自动化代码,这样就有有欠妥当。

python代码通过 python的方式启动 appium 服务。

python执行命令行命令

os.system 执行命令

  1. import os
  2. os.system('ping www.baidu.com')

image.png
os.system 方法可以模拟执行命令行命令。但是缺点是:它是同步的,当命令行中的命令执行完成之后,才会接着往下执行。

subprocess 子进程的方式执行

以后台服务的方式启动appium

  1. # 启动状态 -- 后台启动
  2. with open('./data.log',mode='w',encoding='utf-8') as f:
  3. subprocess.Popen("appium",shell=True,stdout=f)

关闭appium 进程
Windows操作系统 使用netstat 命令来根据端口号找到对应 进程号,再根据进程号使用命令结束即可

查看进程号

Windows命令

  1. netstat -ano | findstr 4723

image.png
根据找到的进程号结束进程

  1. taskkill -f -pid 19760

image.png

mac系统的命令

mac 查看端口占用进程

  1. lsof -i tcp:4723

杀掉进程

  1. kill pid

更改conftest.py 文件,自动启动appium 以及 自动关闭appium

  1. from appium import webdriver
  2. import pytest
  3. import os,sys,subprocess
  4. from appium.webdriver.webdriver import WebDriver
  5. chromedriver= os.path.join(os.path.dirname(os.path.abspath(__file__)),'drivers/chromedriver.exe')
  6. def stop_appium(port):
  7. """
  8. 停止appium
  9. :param port: 启动的端口号
  10. :return:
  11. """
  12. mac_cmd = f"lsof -i tcp:{port}"
  13. win_cmd = f"netstat -ano | findstr {port}"
  14. # 判断操作系统
  15. os_platform = sys.platform
  16. if os_platform == "win32": #windows 系统
  17. win_p = subprocess.Popen(win_cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
  18. for line in win_p.stdout.readlines():
  19. if line:
  20. line = line.decode('utf8')
  21. if "LISTENING" in line:
  22. win_pid = line.split("LISTENING")[1].strip()
  23. os.system(f"taskkill -f -pid {win_pid}")
  24. else: # unix系统
  25. p = subprocess.Popen(mac_cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
  26. for line in p.stdout.readlines():
  27. line = line.decode('utf8')
  28. # print("line",line)
  29. if "node" in line:
  30. stdoutline = line.split(" ")
  31. print(stdoutline)
  32. pid = stdoutline[4]
  33. os.system(f"kill {pid}")
  34. def start_appium(port):
  35. """
  36. 启动appium 服务
  37. :param port: 服务的端口号
  38. :return:
  39. """
  40. stop_appium(port)
  41. cmd = f"appium -p {port}"
  42. logsdir = os.path.join(os.path.dirname(os.path.abspath(__file__)),"logs")
  43. if not os.path.exists(logsdir):
  44. os.mkdir(logsdir)
  45. subprocess.Popen(cmd,shell=True, stdout=open('./logs/'+str(port)+".log",mode='a',encoding="utf8"),
  46. stderr=subprocess.PIPE)
  47. @pytest.fixture(scope='session',autouse=True)
  48. def driver():
  49. # 启动appium服务
  50. start_appium(4723)
  51. desired_caps = {
  52. 'platformName': 'Android', # 测试Android系统
  53. 'platformVersion': '7.1.2', # Android版本 可以在手机的设置中关于手机查看
  54. 'deviceName': '127.0.0.1:62001', # adb devices 命令查看 设置为自己的设备
  55. 'automationName': 'UiAutomator2', # 自动化引擎
  56. 'noReset': False, # 不要重置app的状态
  57. 'fullReset': False, # 不要清理app的缓存数据
  58. 'chromedriverExecutable': chromedriver, # chromedriver 对应的绝对路径
  59. 'appPackage': "org.cnodejs.android.md", # 应用的包名
  60. 'appActivity': ".ui.activity.LaunchActivity" # 应用的活动页名称
  61. }
  62. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_capabilities=desired_caps)
  63. driver.implicitly_wait(5) # 全局的隐式等待时间
  64. yield driver # 将driver 传递出来
  65. # 所有的用例执行之后
  66. stop_appium(4723)
  67. driver.quit()
  68. @pytest.hookimpl(tryfirst=True, hookwrapper=True)
  69. def pytest_runtest_makereport(item, call):
  70. # execute all other hooks to obtain the report object
  71. outcome = yield
  72. # 获取用例的执行结果
  73. rep = outcome.get_result()
  74. # 将执行结果保存到 item 属性中 req.when 执行时
  75. setattr(item, "rep_" + rep.when, rep)
  76. @pytest.fixture(scope='function',autouse=True)
  77. def case_run(driver:webdriver,request):
  78. """
  79. 每个测试用例执行完成之后,如果执行失败截图,截图的名称为测试用例名称+时间格式
  80. :param request:
  81. :return:
  82. """
  83. yield
  84. if request.node.rep_call.failed:
  85. import os,time
  86. screenshots = os.path.join(os.path.dirname(os.path.abspath(__file__)),'screeshots')
  87. if not os.path.exists(screenshots):
  88. os.mkdir(screenshots)
  89. casename:str = request.node.nodeid
  90. print("执行测试用例的名字:",casename)
  91. # 测试用例的名字
  92. # casename = casename.replace('.py::','_')
  93. filename = time.strftime('%Y_%m_%d_%H_%M_%S')+".png"
  94. screenshot_file = os.path.join(screenshots,filename)
  95. # 保存截图
  96. driver.save_screenshot(screenshot_file)

更多参考:
自动化启动appium服务