项目结构
yonghui_app_ui_test/
├── config/
│ └── config.py
├── pages/
│ ├── base_page.py
│ ├── home_page.py
│ ├── search_page.py
│ ├── category_page.py
│ ├── cart_page.py
│ ├── personal_center_page.py
│ └── product_detail_page.py
├── tests/
│ ├── test_home.py
│ ├── test_search.py
│ ├── test_category.py
│ ├── test_cart.py
│ ├── test_personal_center.py
│ └── ...
├── utils/
│ ├── logger.py
│ └── ...
└── run_tests.py
1. 配置文件(config/config.py
)
DESIRED_CAPS = {
"platformName": "Android",
"platformVersion": "你的 Android 版本",
"deviceName": "你的设备名称",
"appPackage": "com.yonghui.mall",
"appActivity": "你的启动 Activity",
"noReset": True
}
APPIUM_SERVER_URL = 'http://localhost:4723/wd/hub'
2. 日志工具(utils/logger.py
)
import logging
def setup_logger():
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
file_handler = logging.FileHandler('test.log')
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
logger = setup_logger()
3. 基础页面类(pages/base_page.py
)
from appium import webdriver
from utils.logger import logger
from config.config import DESIRED_CAPS, APPIUM_SERVER_URL
class BasePage:
def __init__(self):
self.driver = webdriver.Remote(APPIUM_SERVER_URL, DESIRED_CAPS)
logger.info("Appium 驱动已初始化")
def find_element(self, by, value):
try:
element = self.driver.find_element(by, value)
logger.info(f"成功找到元素: {by}={value}")
return element
except Exception as e:
logger.error(f"未找到元素: {by}={value}, 错误信息: {e}")
raise
def click(self, by, value):
element = self.find_element(by, value)
element.click()
logger.info(f"点击元素: {by}={value}")
def send_keys(self, by, value, text):
element = self.find_element(by, value)
element.send_keys(text)
logger.info(f"向元素 {by}={value} 输入文本: {text}")
def is_element_displayed(self, by, value):
try:
element = self.find_element(by, value)
return element.is_displayed()
except Exception:
return False
def close_app(self):
self.driver.quit()
logger.info("Appium 驱动已关闭")
def assert_element_displayed(self, by, value, message):
result = self.is_element_displayed(by, value)
assert result, message
logger.info(f"断言成功: {message}")
4. 首页页面类(pages/home_page.py
)
from pages.base_page import BasePage
from appium.webdriver.common.by import By
class HomePage(BasePage):
ADVERTISEMENT = (By.ID, "com.yonghui.mall:id/advertisement")
SHARE_BUTTON = (By.ID, "com.yonghui.mall:id/share_button")
BACK_HOME_BUTTON = (By.ID, "com.yonghui.mall:id/back_home_button")
PRODUCT = (By.ID, "com.yonghui.mall:id/product")
def click_advertisement(self):
self.click(*self.ADVERTISEMENT)
AD_TITLE = (By.ID, "com.yonghui.mall:id/ad_title")
self.assert_element_displayed(*AD_TITLE, "点击广告后广告页面标题元素未显示")
def click_share_button(self):
self.click(*self.SHARE_BUTTON)
SHARE_CHANNEL_LIST = (By.ID, "com.yonghui.mall:id/share_channel_list")
self.assert_element_displayed(*SHARE_CHANNEL_LIST, "点击分享按钮后分享渠道列表未显示")
def click_back_home(self):
self.click(*self.BACK_HOME_BUTTON)
HOME_LOGO = (By.ID, "com.yonghui.mall:id/home_logo")
self.assert_element_displayed(*HOME_LOGO, "点击返回首页后首页 logo 未显示")
def click_product(self):
self.click(*self.PRODUCT)
PRODUCT_NAME = (By.ID, "com.yonghui.mall:id/product_name")
self.assert_element_displayed(*PRODUCT_NAME, "点击商品后商品详情页商品名称未显示")
5. 商品详情页页面类(pages/product_detail_page.py
)
from pages.base_page import BasePage
from appium.webdriver.common.by import By
class ProductDetailPage(BasePage):
ADD_TO_CART_BUTTON = (By.ID, "com.yonghui.mall:id/add_to_cart_button")
BACK_BUTTON = (By.ID, "com.yonghui.mall:id/back_button")
ADD_SUCCESS_TIP = (By.ID, "com.yonghui.mall:id/add_success_tip")
def add_to_cart(self):
self.click(*self.ADD_TO_CART_BUTTON)
self.assert_element_displayed(*self.ADD_SUCCESS_TIP, "加购商品后加购成功提示未显示")
def click_back(self):
self.click(*self.BACK_BUTTON)
HOME_LOGO = (By.ID, "com.yonghui.mall:id/home_logo")
self.assert_element_displayed(*HOME_LOGO, "点击返回后首页 logo 未显示")
6. 分类页页面类(pages/category_page.py
)
from pages.base_page import BasePage
from appium.webdriver.common.by import By
class CategoryPage(BasePage):
FIRST_CATEGORY = (By.ID, "com.yonghui.mall:id/first_category")
SECOND_CATEGORY = (By.ID, "com.yonghui.mall:id/second_category")
THIRD_CATEGORY = (By.ID, "com.yonghui.mall:id/third_category")
CATEGORY_PRODUCT_ADD_TO_CART = (By.ID, "com.yonghui.mall:id/category_product_add_to_cart")
CATEGORY_PRODUCT_REMOVE_FROM_CART = (By.ID, "com.yonghui.mall:id/category_product_remove_from_cart")
SECOND_CATEGORY_LIST = (By.ID, "com.yonghui.mall:id/second_category_list")
THIRD_CATEGORY_LIST = (By.ID, "com.yonghui.mall:id/third_category_list")
ADD_SUCCESS_TIP = (By.ID, "com.yonghui.mall:id/add_success_tip")
REMOVE_SUCCESS_TIP = (By.ID, "com.yonghui.mall:id/remove_success_tip")
def click_first_category(self):
self.click(*self.FIRST_CATEGORY)
self.assert_element_displayed(*self.SECOND_CATEGORY_LIST, "点击一级分类后二级分类列表未显示")
def click_second_category(self):
self.click(*self.SECOND_CATEGORY)
self.assert_element_displayed(*self.THIRD_CATEGORY_LIST, "点击二级分类后三级分类列表未显示")
def click_third_category(self):
self.click(*self.THIRD_CATEGORY)
PRODUCT_LIST = (By.ID, "com.yonghui.mall:id/product_list")
self.assert_element_displayed(*PRODUCT_LIST, "点击三级分类后商品列表未显示")
def add_product_from_category(self):
self.click(*self.CATEGORY_PRODUCT_ADD_TO_CART)
self.assert_element_displayed(*self.ADD_SUCCESS_TIP, "分类页加购商品后加购成功提示未显示")
def remove_product_from_category(self):
self.click(*self.CATEGORY_PRODUCT_REMOVE_FROM_CART)
self.assert_element_displayed(*self.REMOVE_SUCCESS_TIP, "分类页取消加购商品后取消加购成功提示未显示")
7. 购物车页页面类(pages/cart_page.py
)
from pages.base_page import BasePage
from appium.webdriver.common.by import By
class CartPage(BasePage):
DELETE_PRODUCT_BUTTON = (By.ID, "com.yonghui.mall:id/delete_product_button")
ADD_PRODUCT_IN_CART = (By.ID, "com.yonghui.mall:id/add_product_in_cart")
SWITCH_ADDRESS_BUTTON = (By.ID, "com.yonghui.mall:id/switch_address_button")
CHECKOUT_BUTTON = (By.ID, "com.yonghui.mall:id/checkout_button")
DELETE_SUCCESS_TIP = (By.ID, "com.yonghui.mall:id/delete_success_tip")
ADD_QUANTITY_TIP = (By.ID, "com.yonghui.mall:id/add_quantity_tip")
ADDRESS_SELECT_PAGE = (By.ID, "com.yonghui.mall:id/address_select_page")
def delete_product(self):
self.click(*self.DELETE_PRODUCT_BUTTON)
self.assert_element_displayed(*self.DELETE_SUCCESS_TIP, "购物车删除商品后删除成功提示未显示")
def add_product_in_cart(self):
self.click(*self.ADD_PRODUCT_IN_CART)
self.assert_element_displayed(*self.ADD_QUANTITY_TIP, "购物车添加商品后商品数量增加提示未显示")
def switch_address(self):
self.click(*self.SWITCH_ADDRESS_BUTTON)
self.assert_element_displayed(*self.ADDRESS_SELECT_PAGE, "点击切换地址后地址选择页面未显示")
def go_to_checkout(self):
self.click(*self.CHECKOUT_BUTTON)
CHECKOUT_PAGE_TITLE = (By.ID, "com.yonghui.mall:id/checkout_page_title")
self.assert_element_displayed(*CHECKOUT_PAGE_TITLE, "点击去结算后结算页面标题未显示")
8. 个人中心页页面类(pages/personal_center_page.py
)
from pages.base_page import BasePage
from appium.webdriver.common.by import By
class PersonalCenterPage(BasePage):
PERSONAL_INFO = (By.ID, "com.yonghui.mall:id/personal_info")
AVATAR = (By.ID, "com.yonghui.mall:id/avatar")
COUPONS = (By.ID, "com.yonghui.mall:id/coupons")
YONGHUI_CARD = (By.ID, "com.yonghui.mall:id/yonghui_card")
PERSONAL_INFO_PAGE = (By.ID, "com.yonghui.mall:id/personal_info_page")
COUPON_LIST = (By.ID, "com.yonghui.mall:id/coupon_list")
YONGHUI_CARD_PAGE = (By.ID, "com.yonghui.mall:id/yonghui_card_page")
def click_personal_info(self):
self.click(*self.PERSONAL_INFO)
self.assert_element_displayed(*self.PERSONAL_INFO_PAGE, "点击个人中心信息后个人信息页面未显示")
def click_avatar(self):
self.click(*self.AVATAR)
AVATAR_SETTING = (By.ID, "com.yonghui.mall:id/avatar_setting")
self.assert_element_displayed(*AVATAR_SETTING, "点击头像后头像设置元素未显示")
def click_coupons(self):
self.click(*self.COUPONS)
self.assert_element_displayed(*self.COUPON_LIST, "点击优惠券后优惠券列表未显示")
def click_yonghui_card(self):
self.click(*self.YONGHUI_CARD)
self.assert_element_displayed(*self.YONGHUI_CARD_PAGE, "点击永辉卡后永辉卡页面未显示")
9. 测试用例
首页测试用例(tests/test_home.py
)
import unittest
from pages.home_page import HomePage
from pages.product_detail_page import ProductDetailPage
from utils.logger import logger
class TestHome(unittest.TestCase):
def setUp(self):
self.home_page = HomePage()
def test_home_functions(self):
try:
self.home_page.click_advertisement()
self.home_page.click_share_button()
self.home_page.click_back_home()
self.home_page.click_product()
product_detail_page = ProductDetailPage()
product_detail_page.add_to_cart()
product_detail_page.click_back()
logger.info("首页功能测试通过")
except AssertionError as e:
logger.error(f"首页功能测试断言失败: {e}")
self.fail(f"首页功能测试断言失败: {e}")
except Exception as e:
logger.error(f"首页功能测试出现异常: {e}")
self.fail(f"首页功能测试出现异常: {e}")
def tearDown(self):
self.home_page.close_app()
分类页测试用例(tests/test_category.py
)
import unittest
from pages.category_page import CategoryPage
from utils.logger import logger
class TestCategory(unittest.TestCase):
def setUp(self):
self.category_page = CategoryPage()
def test_category_functions(self):
try:
self.category_page.click_first_category()
self.category_page.click_second_category()
self.category_page.click_third_category()
self.category_page.add_product_from_category()
self.category_page.remove_product_from_category()
logger.info("分类页功能测试通过")
except AssertionError as e:
logger.error(f"分类页功能测试断言失败: {e}")
self.fail(f"分类页功能测试断言失败: {e}")
except Exception as e:
logger.error(f"分类页功能测试出现异常: {e}")
self.fail(f"分类页功能测试出现异常: {e}")
def tearDown(self):
self.category_page.close_app()
购物车页测试用例(tests/test_cart.py
)
import unittest
from pages.cart_page import CartPage
from utils.logger import logger
class TestCart(unittest.TestCase):
def setUp(self):
self.cart_page = CartPage()
def test_cart_functions(self):
try:
self.cart_page.delete_product()
self.cart_page.add_product_in_cart()
self.cart_page.switch_address()
logger.info("购物车页功能测试通过")
except AssertionError as e:
logger.error(f"购物车页功能测试断言失败: {e}")
self.fail(f"购物车页功能测试断言失败: {e}")
except