1. 问:Appium 结合pytest 对APP做自动化测试,有两个测试用例是有前后顺序,第二个测试用例会用到第一个测试用例的按钮,请问如何实现
在使用 Appium 结合 pytest 对应用程序进行自动化测试时,通常需要保证某些测试用例的执行顺序,以确保一个测试用例的执行结果可以被后续的测试用例所使用。具体来说,当一个测试用例依赖于另一个测试用例的状态(比如,一个按钮被点击后),我们需要一种方法来保证这些用例按正确的顺序执行。
在 pytest
中,我们可以通过以下方法来实现这种依赖关系:
- 使用
pytest
的depends
插件。 - 直接调用共享资源。
- 通过
pytest
的 fixture。
方法 1: 使用 pytest
的 depends
插件
pytest-depends
插件可以让我们轻松地管理测试用例之间的依赖关系。首先需要安装插件:
pip install pytest-depends
然后在测试用例中使用 @pytest.mark.dependency
装饰器来标识依赖关系:
import pytest
from appium import webdriver
class TestAppium:
@pytest.fixture(scope="class", autouse=True)
def setup(self):
desired_caps = {
"platformName": "Android",
"deviceName": "emulator-5554",
"appPackage": "com.example.app",
"appActivity": ".MainActivity",
"automationName": "uiautomator2"
}
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
yield
self.driver.quit()
@pytest.mark.dependency(name="test_login")
def test_login(self):
# 假设有一个登录按钮
login_button = self.driver.find_element_by_id("com.example.app:id/login_button")
login_button.click()
# 假设成功登录后出现主页的某个元素
assert self.driver.find_element_by_id("com.example.app:id/home_page")
@pytest.mark.dependency(depends=["test_login"])
def test_functionality_after_login(self):
# 确保登录成功后,继续测试其他功能
button_after_login = self.driver.find_element_by_id("com.example.app:id/button_after_login")
button_after_login.click()
# 检查点击后的效果
assert self.driver.find_element_by_id("com.example.app:id/success_message")
方法 2: 直接调用共享资源
如果你的测试用例较少且简单,可以直接在第二个测试用例中调用第一个测试用例的方法:
import pytest
from appium import webdriver
class TestAppium:
@pytest.fixture(scope="class", autouse=True)
def setup(self):
desired_caps = {
"platformName": "Android",
"deviceName": "emulator-5554",
"appPackage": "com.example.app",
"appActivity": ".MainActivity",
"automationName": "uiautomator2"
}
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
yield
self.driver.quit()
def test_login(self):
# 登录操作
login_button = self.driver.find_element_by_id("com.example.app:id/login_button")
login_button.click()
assert self.driver.find_element_by_id("com.example.app:id/home_page")
def test_functionality_after_login(self):
# 直接调用登录方法
self.test_login()
# 测试功能
button_after_login = self.driver.find_element_by_id("com.example.app:id/button_after_login")
button_after_login.click()
assert self.driver.find_element_by_id("com.example.app:id/success_message")
方法 3: 通过 pytest
的 fixture
pytest
的 fixture 可以在多个测试用例之间共享数据,并实现前置条件的执行。
import pytest
from appium import webdriver
@pytest.fixture(scope="class")
def driver_setup():
desired_caps = {
"platformName": "Android",
"deviceName": "emulator-5554",
"appPackage": "com.example.app",
"appActivity": ".MainActivity",
"automationName": "uiautomator2"
}
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
yield driver
driver.quit()
@pytest.fixture(scope="class")
def login(driver_setup):
# 登录操作
login_button = driver_setup.find_element_by_id("com.example.app:id/login_button")
login_button.click()
# 检查登录是否成功
assert driver_setup.find_element_by_id("com.example.app:id/home_page")
class TestAppium:
def test_login(self, login):
# 登录已经在 fixture 中执行,此处可以不做任何操作
pass
def test_functionality_after_login(self, driver_setup, login):
# 测试功能
button_after_login = driver_setup.find_element_by_id("com.example.app:id/button_after_login")
button_after_login.click()
assert driver_setup.find_element_by_id("com.example.app:id/success_message")
方法 4: 使用 pytest
的 session
级别的 fixture
此方法允许测试用例在同一个测试会话中共享 driver
实例。这样可以保持应用程序状态,并在多个测试用例中使用相同的 session。
import pytest
from appium import webdriver
@pytest.fixture(scope="session")
def driver():
desired_caps = {
"platformName": "Android",
"deviceName": "emulator-5554",
"appPackage": "com.example.app",
"appActivity": ".MainActivity",
"automationName": "uiautomator2"
}
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
yield driver
driver.quit()
@pytest.fixture(scope="session", autouse=True)
def login(driver):
# 登录操作
login_button = driver.find_element_by_id("com.example.app:id/login_button")
login_button.click()
# 检查登录是否成功
assert driver.find_element_by_id("com.example.app:id/home_page")
def test_functionality_1(driver):
# 在登录状态下测试功能1
button1 = driver.find_element_by_id("com.example.app:id/button1")
button1.click()
assert driver.find_element_by_id("com.example.app:id/feature1_success")
def test_functionality_2(driver):
# 在登录状态下测试功能2
button2 = driver.find_element_by_id("com.example.app:id/button2")
button2.click()
assert driver.find_element_by_id("com.example.app:id/feature2_success")
选择适合的方法
- 插件依赖管理 (
pytest-depends
) 是最直接的方式,可以清晰地定义用例依赖关系。 - 直接调用 方法适用于少量测试用例,但不建议用于复杂的测试场景。
- 使用 fixture 提供了更好的灵活性和代码复用,推荐使用。
session
级别的 fixture 更适合需要在同一 session 中保持应用程序状态的测试场景。
通过这些方法,你可以更好地管理测试用例的执行顺序和依赖关系,确保测试用例之间能够正确协作和共享数据。选择适合你的场景的方法,结合实际情况来实现测试自动化。