Appium案例

wen java案例 2

本文目录导读:

Appium案例

  1. 案例一:登录功能测试
  2. 案例二:微信朋友圈发布测试
  3. 案例三:电商App购物流程测试
  4. 案例四:滑动和手势测试
  5. 测试框架和配置
  6. 运行测试

我来为您提供几个常用的Appium自动化测试案例,涵盖不同的应用场景。

登录功能测试

场景:测试iOS/Android登录功能

# login_test.py
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
class LoginTest:
    def __init__(self):
        # Android设备配置
        self.desired_caps = {
            'platformName': 'Android',
            'platformVersion': '10.0',
            'deviceName': 'Android Emulator',
            'appPackage': 'com.example.app',
            'appActivity': '.MainActivity',
            'noReset': True,
            'automationName': 'UiAutomator2'
        }
        # iOS设备配置(如果测试iOS)
        # self.desired_caps = {
        #     'platformName': 'iOS',
        #     'platformVersion': '14.0',
        #     'deviceName': 'iPhone 12',
        #     'app': '/path/to/app.app',
        #     'automationName': 'XCUITest'
        # }
        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', self.desired_caps)
        self.wait = WebDriverWait(self.driver, 10)
    def test_valid_login(self):
        """测试正常登录"""
        try:
            # 等待登录页面元素加载
            username_field = self.wait.until(
                EC.presence_of_element_located((AppiumBy.ID, 'com.example.app:id/username'))
            )
            password_field = self.wait.until(
                EC.presence_of_element_located((AppiumBy.ID, 'com.example.app:id/password'))
            )
            # 输入用户名和密码
            username_field.clear()
            username_field.send_keys('testuser@example.com')
            password_field.clear()
            password_field.send_keys('password123')
            # 点击登录按钮
            login_button = self.driver.find_element(AppiumBy.ID, 'com.example.app:id/login_btn')
            login_button.click()
            # 等待登录成功提示
            success_message = self.wait.until(
                EC.presence_of_element_located((AppiumBy.ID, 'com.example.app:id/success_message'))
            )
            assert success_message.text == "登录成功"
            print("✅ Test passed: 正常登录")
        except Exception as e:
            print(f"❌ Test failed: {str(e)}")
            self.take_screenshot('login_failure')
    def test_invalid_login(self):
        """测试无效登录"""
        try:
            username_field = self.wait.until(
                EC.presence_of_element_located((AppiumBy.ID, 'com.example.app:id/username'))
            )
            password_field = self.wait.until(
                EC.presence_of_element_located((AppiumBy.ID, 'com.example.app:id/password'))
            )
            # 输入错误的凭据
            username_field.clear()
            username_field.send_keys('invaliduser@test.com')
            password_field.clear()
            password_field.send_keys('wrongpassword')
            login_button = self.driver.find_element(AppiumBy.ID, 'com.example.app:id/login_btn')
            login_button.click()
            # 验证错误提示
            error_message = self.wait.until(
                EC.presence_of_element_located((AppiumBy.ID, 'com.example.app:id/error_message'))
            )
            assert "无效" in error_message.text or "错误" in error_message.text
            print("✅ Test passed: 无效登录错误处理")
        except Exception as e:
            print(f"❌ Test failed: {str(e)}")
    def take_screenshot(self, filename):
        """保存截图"""
        timestamp = time.strftime("%Y%m%d_%H%M%S")
        self.driver.save_screenshot(f"./screenshots/{filename}_{timestamp}.png")
    def teardown(self):
        """清理测试环境"""
        self.driver.quit()
if __name__ == "__main__":
    test = LoginTest()
    try:
        test.test_valid_login()
        test.test_invalid_login()
    finally:
        test.teardown()

微信朋友圈发布测试

场景:自动化测试微信朋友圈功能

// WeChatMomentsTest.java
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.touch.WaitOptions;
import io.appium.java_client.touch.offset.PointOption;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import java.net.MalformedURLException;
import java.net.URL;
public class WeChatMomentsTest {
    private AndroidDriver<MobileElement> driver;
    public void setup() throws MalformedURLException {
        DesiredCapabilities caps = new DesiredCapabilities();
        caps.setCapability("platformName", "Android");
        caps.setCapability("platformVersion", "11.0");
        caps.setCapability("deviceName", "emulator-5554");
        caps.setCapability("appPackage", "com.tencent.mm");
        caps.setCapability("appActivity", ".ui.LauncherUI");
        caps.setCapability("noReset", true);
        driver = new AndroidDriver<>(new URL("http://localhost:4723/wd/hub"), caps);
    }
    public void postMoment(String text, String imagePath) {
        WebDriverWait wait = new WebDriverWait(driver, 10);
        try {
            // 打开"发现"页面
            clickElementByText("发现");
            // 点击"朋友圈"
            clickElementByText("朋友圈");
            // 长按发布按钮进入发布界面
            WebElement publishBtn = wait.until(
                ExpectedConditions.elementToBeClickable(By.xpath("//*[@content-desc='发布']"))
            );
            longPress(publishBtn);
            // 输入文字
            WebElement textInput = wait.until(
                ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@text='这一刻的想法...']"))
            );
            textInput.click();
            textInput.sendKeys(text);
            // 选择图片(如果在真机上执行,需要处理相册权限)
            if (imagePath != null) {
                addImageFromGallery(imagePath);
            }
            // 点击发布按钮
            WebElement postBtn = driver.findElement(By.xpath("//*[@text='发表']"));
            postBtn.click();
            // 等待发布成功
            Thread.sleep(2000);
            System.out.println("✅ 朋友圈发布成功");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("❌ 朋友圈发布失败");
        }
    }
    private void clickElementByText(String text) {
        WebDriverWait wait = new WebDriverWait(driver, 10);
        WebElement element = wait.until(
            ExpectedConditions.elementToBeClickable(By.xpath("//*[@text='" + text + "']"))
        );
        element.click();
    }
    private void longPress(WebElement element) {
        // 使用TouchAction模拟长按
        new io.appium.java_client.touch.TouchAction(driver)
            .longPress(io.appium.java_client.touch.offset.ElementOption.element(element))
            .release()
            .perform();
    }
    private void addImageFromGallery(String imagePath) {
        // 具体实现取决于图片选择流程
        System.out.println("选择图片: " + imagePath);
    }
    public void teardown() {
        if (driver != null) {
            driver.quit();
        }
    }
    public static void main(String[] args) throws MalformedURLException {
        WeChatMomentsTest test = new WeChatMomentsTest();
        test.setup();
        test.postMoment("自动化测试发布的朋友圈", null);
        test.teardown();
    }
}

电商App购物流程测试

场景:测试完整的购物流程

# ShoppingFlowTest.py
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.common.touch_action import TouchAction
import unittest
import time
class ShoppingFlowTest(unittest.TestCase):
    def setUp(self):
        """初始化测试环境"""
        desired_caps = {
            'platformName': 'Android',
            'platformVersion': '9.0',
            'deviceName': 'Pixel_3',
            'appPackage': 'com.shop.app',
            'appActivity': '.MainActivity',
            'automationName': 'UiAutomator2',
            'noReset': True
        }
        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
        self.wait = WebDriverWait(self.driver, 10)
    def test_complete_shopping_flow(self):
        """完整购物流程测试"""
        try:
            # 1. 搜索商品
            self.search_product("无线耳机")
            # 2. 选择商品
            self.select_product()
            # 3. 添加到购物车
            self.add_to_cart()
            # 4. 查看购物车
            self.view_cart()
            # 5. 结算
            self.checkout()
            # 6. 选择支付方式
            self.select_payment()
            print("✅ 完整购物流程测试通过")
        except Exception as e:
            self.take_screenshot("shopping_flow_failure")
            self.fail(f"测试失败: {str(e)}")
    def search_product(self, keyword):
        """搜索商品"""
        search_box = self.wait.until(
            EC.element_to_be_clickable((AppiumBy.ID, "com.shop.app:id/search_icon"))
        )
        search_box.click()
        input_box = self.wait.until(
            EC.presence_of_element_located((AppiumBy.ID, "com.shop.app:id/search_input"))
        )
        input_box.send_keys(keyword)
        # 点击搜索按钮
        self.driver.find_element(AppiumBy.ID, "com.shop.app:id/search_btn").click()
        time.sleep(2)
    def select_product(self):
        """选择商品"""
        first_product = self.wait.until(
            EC.element_to_be_clickable((AppiumBy.XPATH, 
                "//*[@resource-id='com.shop.app:id/product_list']//*[@class='android.widget.RelativeLayout'][1]"))
        )
        first_product.click()
        time.sleep(1)
    def add_to_cart(self):
        """添加到购物车"""
        add_cart_btn = self.wait.until(
            EC.element_to_be_clickable((AppiumBy.ID, "com.shop.app:id/add_cart_btn"))
        )
        add_cart_btn.click()
        # 确认添加到购物车
        confirm_btn = self.wait.until(
            EC.element_to_be_clickable((AppiumBy.ID, "com.shop.app:id/confirm_btn"))
        )
        confirm_btn.click()
    def view_cart(self):
        """查看购物车"""
        cart_icon = self.wait.until(
            EC.element_to_be_clickable((AppiumBy.ID, "com.shop.app:id/cart_icon"))
        )
        cart_icon.click()
        # 验证商品在购物车中
        assert "无线耳机" in self.driver.page_source, "购物车中没有找到商品"
    def checkout(self):
        """结算"""
        checkout_btn = self.wait.until(
            EC.element_to_be_clickable((AppiumBy.ID, "com.shop.app:id/checkout_btn"))
        )
        checkout_btn.click()
    def select_payment(self):
        """选择支付方式"""
        # 选择微信支付
        wechat_pay = self.wait.until(
            EC.element_to_be_clickable((AppiumBy.XPATH, "//*[@text='微信支付']"))
        )
        wechat_pay.click()
        # 确认支付
        pay_btn = self.wait.until(
            EC.element_to_be_clickable((AppiumBy.ID, "com.shop.app:id/pay_btn"))
        )
        pay_btn.click()
    def take_screenshot(self, filename):
        self.driver.save_screenshot(f"./screenshots/{filename}_{time.time()}.png")
    def tearDown(self):
        self.driver.quit()
if __name__ == "__main__":
    unittest.main()

滑动和手势测试

场景:手势操作测试

# GesturesTest.py
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.common.touch_action import TouchAction
from appium.webdriver.common.touch import Touch
import time
class GesturesTest:
    def __init__(self):
        self.driver = self.setup_driver()
    def setup_driver(self):
        # iOS设备配置
        desired_caps = {
            'platformName': 'iOS',
            'platformVersion': '14.0',
            'deviceName': 'iPhone 12',
            'app': '/path/to/app.app',
            'automationName': 'XCUITest',
            'udid': 'DEVICE_UDID'
        }
        return webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
    def swipe_test(self):
        """测试滑动操作"""
        try:
            # 向上滑动(下拉刷新)
            TouchAction(self.driver).\
                press(x=200, y=800).\
                move_to(x=200, y=200).\
                release().perform()
            time.sleep(2)
            # 向下滑动(查看更多)
            TouchAction(self.driver).\
                press(x=200, y=300).\
                move_to(x=200, y=700).\  
                release().perform()
            time.sleep(2)
            # 向左滑动(切换页面)
            TouchAction(self.driver).\
                press(x=350, y=500).\
                move_to(x=50, y=500).\
                release().perform()
            time.sleep(2)
            print("✅ 滑动操作测试通过")
        except Exception as e:
            print(f"❌ 滑动操作测试失败: {str(e)}")
    def pinch_zoom_test(self):
        """测试缩放手势"""
        try:
            element = self.driver.find_element(AppiumBy.ID, "image_viewer")
            # 放大操作
            TouchAction(self.driver).\
                press(element, element.X + 50, element.Y).\
                wait(1000).\
                move_to(element.X + 150, element.Y).\
                release().\
                press(element, element.X - 50, element.Y).\
                wait(1000).\
                move_to(element.X - 150, element.Y).\
                release().perform()
            time.sleep(2)
            # 缩小操作
            TouchAction(self.driver).\
                press(element, element.X + 150, element.Y).\
                wait(1000).\
                move_to(element.X + 50, element.Y).\
                release().\
                press(element, element.X - 150, element.Y).\
                wait(1000).\
                move_to(element.X - 50, element.Y).\
                release().perform()
            print("✅ 缩放手势测试通过")
        except Exception as e:
            print(f"❌ 缩放手势测试失败: {str(e)}")
    def tap_and_hold_test(self):
        """测试长按手势"""
        try:
            element = self.driver.find_element(AppiumBy.ID, "long_press_element")
            # 长按操作
            TouchAction(self.driver).\
                long_press(element, duration=3000).\
                release().perform()
            time.sleep(1)
            # 验证长按后的效果
            context_menu = self.driver.find_element(AppiumBy.ID, "context_menu")
            assert context_menu.is_displayed(), "长按菜单未弹出"
            print("✅ 长按手势测试通过")
        except Exception as e:
            print(f"❌ 长按手势测试失败: {str(e)}")
    def teardown(self):
        self.driver.quit()
if __name__ == "__main__":
    test = GesturesTest()
    try:
        test.swipe_test()
        test.pinch_zoom_test()
        test.tap_and_hold_test()
    finally:
        test.teardown()

测试框架和配置

Page Object Model 测试框架

# pages/base_page.py
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class BasePage:
    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(self.driver, 10)
    def find_element(self, by, value):
        return self.wait.until(
            EC.presence_of_element_located((by, value))
        )
    def click_element(self, by, value):
        element = self.find_element(by, value)
        element.click()
    def input_text(self, by, value, text):
        element = self.find_element(by, value)
        element.clear()
        element.send_keys(text)
    def get_text(self, by, value):
        element = self.find_element(by, value)
        return element.text
    def is_element_present(self, by, value):
        try:
            self.find_element(by, value)
            return True
        except:
            return False
# pages/login_page.py
class LoginPage(BasePage):
    def __init__(self, driver):
        super().__init__(driver)
        self.username_input = (AppiumBy.ID, "com.example.app:id/username")
        self.password_input = (AppiumBy.ID, "com.example.app:id/password")
        self.login_button = (AppiumBy.ID, "com.example.app:id/login_btn")
    def login(self, username, password):
        self.input_text(*self.username_input, username)
        self.input_text(*self.password_input, password)
        self.click_element(*self.login_button)
# tests/test_login_flow.py
import unittest
from pages.login_page import LoginPage
class TestLoginFlow(unittest.TestCase):
    def test_initial_setup(self):
        # 初始化drivers和页面对象
        self.driver = setup_driver()
        self.login_page = LoginPage(self.driver)
    def test_valid_login(self):
        self.login_page.login("testuser@example.com", "password123")
        # 验证登录成功
        assert "登录成功" in self.driver.page_source
    def test_invalid_login(self):
        self.login_page.login("invalid@test.com", "wrongpass")
        # 验证错误信息
        assert "无效" in self.driver.page_source

运行测试

命令行运行

# 运行特定测试
python -m pytest test_login.py -v
# 运行Page Object框架测试
python -m pytest tests/test_login_flow.py -v
# 生成测试报告
python -m pytest test_*.py -v --html=report.html

并行执行测试

# conftest.py
import pytest
from appium import webdriver
@pytest.fixture(scope="function")
def android_driver():
    caps = {...
    }
    driver = webdriver.Remote('http://localhost:4723/wd/hub', caps)
    yield driver
    driver.quit()
@pytest.fixture(scope="function")
def ios_driver():
    caps = {...}
    driver = webdriver.Remote('http://localhost:4723/wd/hub', caps)
    yield driver
    driver.quit()

这些案例涵盖了Appium自动化测试的常见场景,包括:

  1. 基本功能测试(登录、注册)
  2. 复杂流程测试(购物流程)
  3. 手势操作测试(滑动、缩放、长按)
  4. 页面对象模型(POM框架)
  5. 多平台支持(Android和iOS)

每个案例都考虑了异常处理和最佳实践,您可以根据具体的应用场景调整和扩展这些代码。

抱歉,评论功能暂时关闭!