Skip to content

ERPNext系统Web自动化测试

1. Web自动化测试概述

1.1 测试目标

验证ERPNext系统的Web界面功能,确保用户界面操作的正确性、稳定性和用户体验质量。

1.2 测试范围

  • 客户管理界面测试
  • 销售订单界面测试
  • 采购订单界面测试
  • 库存管理界面测试
  • 财务管理界面测试
  • 权限管理界面测试
  • 报表界面测试

1.3 技术栈

  • 测试框架:Selenium WebDriver + Python
  • 页面对象模型:Page Object Pattern
  • 测试报告:Allure
  • 持续集成:Jenkins

2. 测试环境配置

2.1 环境要求

  • Python 3.8+
  • Chrome浏览器
  • ChromeDriver
  • Selenium WebDriver

2.2 项目结构

ERPNextWebTest/
├── pages/           # 页面对象
├── tests/           # 测试用例
├── utils/           # 工具类
├── config/          # 配置文件
├── reports/         # 测试报告
└── requirements.txt # 依赖包

3. 页面对象设计

3.1 登录页面

class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        self.username_input = "//input[@name='login']"
        self.password_input = "//input[@name='password']"
        self.login_button = "//button[@type='submit']"
        self.error_message = "//div[@class='alert alert-danger']"

    def login(self, username, password):
        """执行登录操作"""
        self.driver.find_element(By.XPATH, self.username_input).send_keys(username)
        self.driver.find_element(By.XPATH, self.password_input).send_keys(password)
        self.driver.find_element(By.XPATH, self.login_button).click()

    def get_error_message(self):
        """获取错误信息"""
        return self.driver.find_element(By.XPATH, self.error_message).text

3.2 客户管理页面

class CustomerPage:
    def __init__(self, driver):
        self.driver = driver
        self.add_customer_btn = "//button[contains(text(),'新增客户')]"
        self.customer_name_input = "//input[@data-fieldname='customer_name']"
        self.customer_type_select = "//select[@data-fieldname='customer_type']"
        self.save_button = "//button[contains(text(),'保存')]"
        self.customer_list = "//div[@class='list-row']"

    def add_customer(self, name, customer_type):
        """添加新客户"""
        self.driver.find_element(By.XPATH, self.add_customer_btn).click()
        self.driver.find_element(By.XPATH, self.customer_name_input).send_keys(name)
        self.driver.find_element(By.XPATH, self.customer_type_select).send_keys(customer_type)
        self.driver.find_element(By.XPATH, self.save_button).click()

    def search_customer(self, name):
        """搜索客户"""
        search_input = "//input[@placeholder='搜索客户']"
        self.driver.find_element(By.XPATH, search_input).send_keys(name)
        self.driver.find_element(By.XPATH, search_input).send_keys(Keys.ENTER)

3.3 销售订单页面

class SalesOrderPage:
    def __init__(self, driver):
        self.driver = driver
        self.new_order_btn = "//button[contains(text(),'新建销售订单')]"
        self.customer_select = "//input[@data-fieldname='customer']"
        self.item_table = "//div[@class='grid-row']"
        self.add_item_btn = "//button[contains(text(),'添加项目')]"
        self.submit_button = "//button[contains(text(),'提交')]"

    def create_sales_order(self, customer, items):
        """创建销售订单"""
        self.driver.find_element(By.XPATH, self.new_order_btn).click()
        self.driver.find_element(By.XPATH, self.customer_select).send_keys(customer)

        for item in items:
            self.driver.find_element(By.XPATH, self.add_item_btn).click()
            # 添加商品信息

        self.driver.find_element(By.XPATH, self.submit_button).click()

4. 测试用例设计

4.1 登录功能测试

class TestLogin:
    def test_valid_login(self):
        """测试有效用户登录"""
        login_page = LoginPage(self.driver)
        login_page.login("test@example.com", "password123")
        assert "仪表板" in self.driver.page_source

    def test_invalid_login(self):
        """测试无效用户登录"""
        login_page = LoginPage(self.driver)
        login_page.login("invalid@example.com", "wrongpassword")
        assert "用户名或密码错误" in login_page.get_error_message()

4.2 客户管理测试

class TestCustomerManagement:
    def test_add_customer(self):
        """测试添加客户"""
        customer_page = CustomerPage(self.driver)
        customer_page.add_customer("测试客户", "个人")
        assert "测试客户" in self.driver.page_source

    def test_search_customer(self):
        """测试搜索客户"""
        customer_page = CustomerPage(self.driver)
        customer_page.search_customer("测试客户")
        assert len(customer_page.get_customer_list()) > 0

4.3 销售订单测试

class TestSalesOrder:
    def test_create_sales_order(self):
        """测试创建销售订单"""
        sales_order_page = SalesOrderPage(self.driver)
        items = [{"name": "商品A", "qty": 2, "price": 100}]
        sales_order_page.create_sales_order("测试客户", items)
        assert "销售订单已创建" in self.driver.page_source

5. 测试数据管理

5.1 测试数据文件

{
    "test_users": [
        {
            "username": "admin@example.com",
            "password": "admin123",
            "role": "管理员"
        },
        {
            "username": "sales@example.com", 
            "password": "sales123",
            "role": "销售员"
        }
    ],
    "test_customers": [
        {
            "name": "测试客户A",
            "type": "个人",
            "email": "customerA@example.com"
        },
        {
            "name": "测试客户B",
            "type": "企业",
            "email": "customerB@example.com"
        }
    ]
}

5.2 数据管理工具类

class DataManager:
    def __init__(self):
        self.test_data = self.load_test_data()

    def load_test_data(self):
        """加载测试数据"""
        with open('test_data.json', 'r', encoding='utf-8') as f:
            return json.load(f)

    def get_test_user(self, role):
        """获取测试用户"""
        for user in self.test_data['test_users']:
            if user['role'] == role:
                return user
        return None

    def get_test_customer(self, name):
        """获取测试客户"""
        for customer in self.test_data['test_customers']:
            if customer['name'] == name:
                return customer
        return None

6. 测试执行和报告

6.1 测试执行脚本

import pytest
from selenium import webdriver
from pages.login_page import LoginPage
from utils.data_manager import DataManager

class TestExecution:
    def setup_method(self):
        """测试前置条件"""
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.data_manager = DataManager()

    def teardown_method(self):
        """测试后置条件"""
        self.driver.quit()

    def test_complete_workflow(self):
        """测试完整业务流程"""
        # 登录
        login_page = LoginPage(self.driver)
        user = self.data_manager.get_test_user("销售员")
        login_page.login(user['username'], user['password'])

        # 添加客户
        customer_page = CustomerPage(self.driver)
        customer = self.data_manager.get_test_customer("测试客户A")
        customer_page.add_customer(customer['name'], customer['type'])

        # 创建销售订单
        sales_order_page = SalesOrderPage(self.driver)
        items = [{"name": "商品A", "qty": 1, "price": 100}]
        sales_order_page.create_sales_order(customer['name'], items)

        # 验证结果
        assert "订单创建成功" in self.driver.page_source

6.2 Allure报告配置

import allure

@allure.feature("ERPNext系统测试")
@allure.story("客户管理")
class TestCustomerManagement:
    @allure.title("添加新客户")
    @allure.description("测试添加新客户功能")
    def test_add_customer(self):
        with allure.step("打开客户管理页面"):
            customer_page = CustomerPage(self.driver)

        with allure.step("填写客户信息"):
            customer_page.add_customer("测试客户", "个人")

        with allure.step("验证客户添加成功"):
            assert "测试客户" in self.driver.page_source

7. 持续集成配置

7.1 Jenkins Pipeline

pipeline {
    agent any

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', url: 'https://github.com/example/erpnext-web-test.git'
            }
        }

        stage('Setup Environment') {
            steps {
                sh 'pip install -r requirements.txt'
                sh 'python -m pytest --version'
            }
        }

        stage('Run Tests') {
            steps {
                sh 'python -m pytest tests/ --allure-results-dir=allure-results'
            }
        }

        stage('Generate Report') {
            steps {
                allure includeProperties: false, jdk: '', results: [[path: 'allure-results']]
            }
        }
    }

    post {
        always {
            publishHTML([
                allowMissing: false,
                alwaysLinkToLastBuild: true,
                keepAll: true,
                reportDir: 'allure-results',
                reportFiles: 'index.html',
                reportName: 'Allure Report'
            ])
        }
    }
}

8. 最佳实践

8.1 页面对象模式

  • 每个页面创建独立的页面对象类
  • 使用显式等待替代隐式等待
  • 封装常用的页面操作方法

8.2 测试数据管理

  • 使用外部文件管理测试数据
  • 支持多环境数据配置
  • 实现数据清理和恢复机制

8.3 异常处理

  • 添加截图功能用于失败分析
  • 实现重试机制处理不稳定元素
  • 记录详细的测试日志

8.4 性能优化

  • 使用无头浏览器进行快速测试
  • 并行执行测试用例
  • 优化测试数据准备时间

9. 故障排除

9.1 常见问题

  • 元素定位失败:检查页面结构变化,更新定位器
  • 测试不稳定:增加等待时间,使用显式等待
  • 数据冲突:实现测试数据隔离和清理

9.2 调试技巧

  • 使用浏览器开发者工具分析页面结构
  • 添加详细的日志输出
  • 使用截图功能记录测试状态

10. 总结

ERPNext系统Web自动化测试框架提供了完整的测试解决方案,包括页面对象设计、测试用例管理、数据管理、报告生成等功能。通过持续集成和最佳实践,确保测试的稳定性和可维护性。