杰瑞科技汇

Python+Appium+TestNG如何自动化测试?

Of course! This is a very common and powerful combination for automated mobile testing. Let's break down how to use Python, Appium, and TestNG together.

Python+Appium+TestNG如何自动化测试?-图1
(图片来源网络,侵删)

First, a crucial clarification: TestNG is a Java framework. You cannot directly use the @Test, @BeforeMethod, etc., annotations in Python.

However, the spirit and structure of TestNG are so popular that the Python community has adopted them. The primary way to achieve a TestNG-like experience in Python is by using the pytest framework with specific plugins.

So, the modern, recommended stack is: Python + Appium + Pytest (with plugins for TestNG-like features)

I will guide you through this setup, which is the industry standard. I'll also briefly touch on the older, less common way of using a Python-to-Java bridge for TestNG.

Python+Appium+TestNG如何自动化测试?-图2
(图片来源网络,侵删)

The Recommended Approach: Python + Appium + Pytest

This combination gives you the best of all worlds: Python's readability, Appium's cross-platform power, and Pytest's flexibility and rich plugin ecosystem.

Key Pytest Plugins for TestNG-like Features:

  1. pytest-testng: This plugin allows you to use TestNG-style XML files to define your test suites, test methods, and parameters. This is the closest you can get to the native TestNG XML configuration.
  2. pytest-metadata: Useful for adding metadata to your test reports, similar to TestNG's built-in reporting.
  3. pytest-html: Generates a beautiful, standalone HTML report, which is the Python equivalent of TestNG's HTML reports.
  4. pytest-xdist: For parallel test execution, a key feature for speeding up test suites.

Step-by-Step Guide

Step 1: Project Setup

Let's create a structured project directory.

appium-python-testng/
├── tests/                  # Your test files will go here
│   └── test_calculator.py
├── pages/                  # Page Object Model (POM) classes
│   └── calculator_page.py
├── config/
│   └── capabilities.py    # Appium capabilities
│   └── testng.xml          # Our TestNG-style configuration file
├── requirements.txt        # Python dependencies
└── README.md

Step 2: Install Dependencies

Create a requirements.txt file with the following content:

# For Appium and mobile automation
Appium-Python-Client
pytest
pytest-testng
pytest-html
pytest-metadata

Now, install them:

pip install -r requirements.txt

Step 3: Configure Appium Capabilities (config/capabilities.py)

This file defines how Appium should connect to your device or emulator.

# config/capabilities.py
# For Android
desired_caps = {
    'platformName': 'Android',
    'deviceName': 'Pixel_4_API_30', # Change this to your device/emulator name
    'app': '/path/to/your/app.apk', # Absolute path to your APK
    'automationName': 'UiAutomator2',
    'appPackage': 'com.google.android.calculator', # Example: Calculator app
    'appActivity': 'com.android.calculator2.Calculator' # Example: Calculator activity
}
# For iOS (just for reference)
# desired_caps = {
#     'platformName': 'iOS',
#     'deviceName': 'iPhone 14',
#     'app': '/path/to/your.app',
#     'automationName': 'XCUITest',
#     'wdaStartupRetries': 4,
#     'wdaStartupTimeout': 120
# }

Step 4: Create a TestNG-style XML Configuration (config/testng.xml)

This is the core of the TestNG-like setup. You define your test suites and the test classes/methods to run.

<!-- config/testng.xml -->
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Calculator Test Suite" verbose="1">
    <test name="Basic Arithmetic Tests">
        <classes>
            <class name="tests.test_calculator.CalculatorTests"/>
        </classes>
    </test>
</suite>

Note: The name attribute for the <class> should be the full path to your test class (module path.ClassName).

Step 5: Implement the Page Object Model (POM)

POM is a design pattern that makes your tests more readable and maintainable.

# pages/calculator_page.py
from appium.webdriver.common.appiumby import AppiumBy
class CalculatorPage:
    def __init__(self, driver):
        self.driver = driver
    # Locators
    _field_result = (AppiumBy.ID, 'com.google.android.calculator:id/result_final')
    _btn_5 = (AppiumBy.ID, 'com.google.android.calculator:id/digit_5')
    _btn_plus = (AppiumBy.ACCESSIBILITY_ID, "plus")
    _btn_equals = (AppiumBy.ID, 'com.google.android.calculator:id/eq')
    _btn_6 = (AppiumBy.ID, 'com.google.android.calculator:id/digit_6')
    def get_result_text(self):
        return self.driver.find_element(*self._field_result).text
    def calculate(self, num1, operator, num2):
        # Click first number
        if num1 == 5:
            self.driver.find_element(*self._btn_5).click()
        elif num1 == 6:
            self.driver.find_element(*self._btn_6).click()
        # Click operator
        if operator == '+':
            self.driver.find_element(*self._btn_plus).click()
        elif operator == '-':
            self.driver.find_element(*self._btn_plus).click() # Assuming minus is 'plus' for this example
        # Click second number
        if num2 == 5:
            self.driver.find_element(*self._btn_5).click()
        elif num2 == 6:
            self.driver.find_element(*self._btn_6).click()
        # Click equals
        self.driver.find_element(*self._btn_equals).click()
        return self.get_result_text()

Step 6: Write the Test (tests/test_calculator.py)

Here we write the actual test logic. The pytest-testng plugin will automatically pick up the testng_suite fixture and use the testng.xml file.

# tests/test_calculator.py
import pytest
from config.capabilities import desired_caps
from appium import webdriver
from pages.calculator_page import CalculatorPage
@pytest.fixture(scope='class')
def testng_suite(request):
    # This fixture is provided by the pytest-testng plugin.
    # It reads the testng.xml file and sets up the test class.
    pass
@pytest.fixture(scope='class')
def driver(request):
    # Setup: Start the Appium driver
    driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
    yield driver
    # Teardown: Quit the driver
    driver.quit()
@pytest.fixture(scope='class')
def calculator_page(driver):
    return CalculatorPage(driver)
class CalculatorTests:
    # This test will be discovered by pytest-testng because it's in a class
    # defined in testng.xml
    def test_addition(self, calculator_page):
        result = calculator_page.calculate(5, '+', 6)
        assert result == "11"
    def test_subtraction(self, calculator_page):
        # Assuming subtraction works with the same button for simplicity
        result = calculator_page.calculate(6, '-', 5)
        assert result == "1"

Step 7: Run Your Tests

You can now run your test suite using pytest, and it will automatically use the testng.xml file.

# Run tests specified in testng.xml
pytest
# Run tests and generate an HTML report
pytest --html=reports/report.html
# Run tests in parallel (if you have multiple devices/instances)
# First, install pytest-xdist: pip install pytest-xdist
pytest -n 2 # Run tests on 2 workers

When you run pytest, the pytest-testng plugin will find your config/testng.xml file, identify the CalculatorTests class, and execute the test methods within it.


The Old (Not Recommended) Way: Python-Java Bridge

There was a time when people used a bridge like JPype or PyJNIus to call a Java TestNG runner from Python. This is highly discouraged today because:

  • Complexity: It adds a heavy dependency on the Java Virtual Machine (JVM) in your Python environment.
  • Maintenance: You have to manage two language ecosystems (Python and Java).
  • Performance: The bridge adds overhead.
  • Modern Alternatives: Pytest with plugins is now mature, powerful, and the de-facto standard.

Summary: Python + Appium + Pytest vs. TestNG

Feature Python + Appium + Pytest Java + Appium + TestNG
Language
分享:
扫描分享到社交APP
上一篇
下一篇