软件测试中的ST/IT/UT/DT

目录

UT

Unit Test,单元测试

测试对象:最小的可测试单元(函数、方法、类)

测试范围:单个代码单元的内部逻辑

测试人员:开发人员

测试时机:编码阶段

实现方法:

python 复制代码
# Python unittest 示例
import unittest

def add(a, b):
    return a + b

class TestAddFunction(unittest.TestCase):
    def test_add_positive(self):
        self.assertEqual(add(2, 3), 5)
    
    def test_add_negative(self):
        self.assertEqual(add(-1, -1), -2)
    
    def test_add_zero(self):
        self.assertEqual(add(0, 5), 5)

# C++ Google Test 示例
#include <gtest/gtest.h>

int multiply(int a, int b) {
    return a * b;
}

TEST(MultiplyTest, PositiveNumbers) {
    EXPECT_EQ(multiply(3, 4), 12);
}

TEST(MultiplyTest, WithZero) {
    EXPECT_EQ(multiply(0, 5), 0);
    EXPECT_EQ(multiply(7, 0), 0);
}

实现工具:

  • Python: unittest, pytest
  • Java: JUnit, TestNG
  • C++: Google Test, Catch2
  • JavaScript: Jest, Mocha
  • Go: testing package

最佳实践:

  • 测试隔离:每个测试独立,不依赖外部资源
  • 快速执行:测试应在毫秒级别完成
  • 高覆盖率:追求80%+的代码覆盖率

FIRST原则:

  • Fast(快速)
  • Independent(独立)
  • Repeatable(可重复)
  • Self-validating(自验证)
  • Timely(及时)

IT

Integration Test,集成测试

测试对象:模块/组件之间的接口和交互

测试范围:多个单元的集成

测试人员:开发人员/测试工程师

测试时机:单元测试之后

实现方法:

python 复制代码
# 数据库集成测试示例
import pytest
import sqlite3

class DatabaseService:
    def __init__(self, db_path):
        self.conn = sqlite3.connect(db_path)
    
    def add_user(self, username, email):
        cursor = self.conn.cursor()
        cursor.execute("INSERT INTO users (username, email) VALUES (?, ?)", 
                      (username, email))
        self.conn.commit()
        return cursor.lastrowid
    
    def get_user(self, user_id):
        cursor = self.conn.cursor()
        cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
        return cursor.fetchone()

@pytest.fixture
def db_service(tmp_path):
    # 创建临时数据库
    db_path = tmp_path / "test.db"
    conn = sqlite3.connect(db_path)
    conn.execute("""
        CREATE TABLE users (
            id INTEGER PRIMARY KEY,
            username TEXT NOT NULL,
            email TEXT NOT NULL
        )
    """)
    conn.commit()
    conn.close()
    
    return DatabaseService(db_path)

def test_user_crud(db_service):
    # 测试完整的CRUD流程
    user_id = db_service.add_user("testuser", "test@example.com")
    assert user_id == 1
    
    user = db_service.get_user(user_id)
    assert user[1] == "testuser"
    assert user[2] == "test@example.com"

实现工具:

  • API测试: Postman, Insomnia, RestAssured
  • 数据库测试: Testcontainers, DBUnit
  • 消息队列测试: Testcontainers with Kafka/RabbitMQ
  • 微服务测试: Pact, WireMock

测试类型:

  • Big Bang:所有模块一起集成测试
  • Top-Down:从顶层开始向下集成
  • Bottom-Up:从底层开始向上集成
  • Sandwich:结合自上而下和自下而上

ST

System Test,系统测试

测试对象:完整的软件系统

测试范围:端到端功能、性能、安全等

测试人员:测试工程师/QA团队

测试时机:集成测试之后

实现方法:

python

python 复制代码
# 电商系统测试示例
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

class TestEcommerceSystem:
    def setup_method(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(10)
    
    def test_complete_purchase_flow(self):
        # 1. 访问网站
        self.driver.get("https://example-shop.com")
        
        # 2. 搜索商品
        search_box = self.driver.find_element(By.NAME, "q")
        search_box.send_keys("笔记本电脑")
        search_box.send_keys(Keys.RETURN)
        
        # 3. 选择商品
        product = self.driver.find_element(By.CSS_SELECTOR, ".product-list li:first-child")
        product.click()
        
        # 4. 添加到购物车
        add_to_cart = self.driver.find_element(By.ID, "add-to-cart")
        add_to_cart.click()
        
        # 5. 结账
        self.driver.find_element(By.LINK_TEXT, "去结算").click()
        
        # 6. 填写收货信息
        self.driver.find_element(By.ID, "address").send_keys("测试地址")
        self.driver.find_element(By.ID, "phone").send_keys("13800138000")
        
        # 7. 提交订单
        self.driver.find_element(By.ID, "submit-order").click()
        
        # 8. 验证订单创建成功
        success_msg = self.driver.find_element(By.CLASS_NAME, "order-success")
        assert "订单创建成功" in success_msg.text
    
    def teardown_method(self):
        self.driver.quit()

测试类型:

  • 功能测试:验证系统功能是否符合需求
  • 性能测试:负载测试、压力测试、耐久测试
  • 安全测试:渗透测试、漏洞扫描
  • 兼容性测试:不同浏览器、操作系统、设备
  • 可用性测试:用户体验测试

实现工具:

  • Web UI测试: Selenium, Cypress, Playwright
  • 移动端测试: Appium, Espresso, XCUITest
  • 性能测试: JMeter, Gatling, Locust
  • 安全测试: OWASP ZAP, Burp Suite
  • API E2E测试: Karate, RestAssured

DT

Development Test,开发测试

这是一个不太标准的术语,通常有两种解释:

解释1:开发阶段的测试(Development Testing)

包含所有开发过程中的测试活动:

text

┌─────────────────────────────────────────────┐

│ Development Testing │

├─────────────┬─────────────┬─────────────────┤

│ Unit Test │ IT │ System Test │

│ (UT) │ │ (ST) │

└─────────────┴─────────────┴─────────────────┘

解释2:开发人员测试(Developer Testing)

开发人员在编码阶段进行的各种测试:

  • 单元测试(UT)
  • 集成测试(IT的一部分)
  • 代码审查
  • 静态代码分析
  • 契约测试

实现方法(开发测试流程):

python

python 复制代码
# 完整的开发测试流程示例
import pytest
from unittest.mock import Mock, patch
import requests

# 1. 单元测试
def calculate_discount(price, discount_rate):
    if price < 0 or discount_rate < 0 or discount_rate > 1:
        raise ValueError("Invalid input")
    return price * (1 - discount_rate)

# 2. 集成测试(与外部服务)
class PaymentService:
    def __init__(self, api_url):
        self.api_url = api_url
    
    def process_payment(self, amount, card_token):
        response = requests.post(
            f"{self.api_url}/payments",
            json={"amount": amount, "card_token": card_token}
        )
        response.raise_for_status()
        return response.json()

# 3. 模拟和契约测试
def test_payment_service_integration():
    with patch('requests.post') as mock_post:
        # 模拟支付网关响应
        mock_response = Mock()
        mock_response.json.return_value = {"status": "success", "id": "pay_123"}
        mock_response.raise_for_status = Mock()
        mock_post.return_value = mock_response
        
        service = PaymentService("https://api.payment.com")
        result = service.process_payment(100, "tok_123")
        
        assert result["status"] == "success"
        mock_post.assert_called_once()

# 4. 端到端测试(简化版)
def test_e2e_checkout():
    # 模拟用户完整流程
    cart = ShoppingCart()
    cart.add_item("item1", 2)
    
    payment = PaymentProcessor()
    result = payment.process(cart.total(), "test_card")
    
    assert result.success
    assert cart.is_empty()

完整的测试金字塔模型

text

复制代码
   /\
  /  \     E2E/ST (少量)
 /    \
/------\   Integration Tests (中等)

/

/---------\ Unit Tests (大量)

/____________\

各层测试比例建议:

  • UT: 70-80%
  • IT: 10-20%
  • ST/E2E: 5-10%

实现框架对比

测试类型 推荐框架 测试速度 维护成本 隔离性

UT pytest, JUnit, Google Test 快 低 高

IT Testcontainers, WireMock 中 中 中

ST Selenium, Cypress, JMeter 慢 高 低

现代测试策略

  1. 测试驱动开发(TDD)
python 复制代码
# 1. 先写测试
def test_divide():
    assert divide(10, 2) == 5
    assert divide(10, 0) raises ZeroDivisionError

# 2. 实现功能
def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("Cannot divide by zero")
    return a / b

# 3. 重构优化
  1. 行为驱动开发(BDD)
bash 复制代码
gherkin

# feature文件
Feature: 用户登录
  Scenario: 成功登录
    Given 用户访问登录页面
    When 输入有效的用户名和密码
    Then 显示欢迎信息
    
  Scenario: 登录失败
    Given 用户访问登录页面
    When 输入错误的密码
    Then 显示错误消息
  1. 契约测试(微服务架构)
java 复制代码
java

// 消费者驱动契约
@Pact(consumer = "OrderService", provider = "PaymentService")
public RequestResponsePact createPaymentPact(PactDslWithProvider builder) {
    return builder
        .given("payment service is available")
        .uponReceiving("a request to process payment")
        .path("/payments")
        .method("POST")
        .willRespondWith()
        .status(200)
        .body(new PactDslJsonBody()
            .stringType("status", "success")
            .stringType("transactionId"))
        .toPact();
}

CI/CD 中的测试流水线

yaml 复制代码
yaml

# .gitlab-ci.yml 示例
stages:
  - test
  
unit_tests:
  stage: test
  script:
    - pytest tests/unit/ --cov=src --cov-report=xml
  
integration_tests:
  stage: test
  script:
    - docker-compose up -d  # 启动依赖服务
    - pytest tests/integration/
    - docker-compose down
  
system_tests:
  stage: test
  script:
    - npm run e2e  # 运行端到端测试
  only:
    - main  # 只在主分支运行系统测试

最佳实践总结

对于 UT:

✅ 使用依赖注入便于mock

✅ 每个测试一个断言

✅ 测试异常和边界情况

❌ 避免测试私有方法

❌ 不要依赖外部服务

对于 IT:

✅ 使用测试数据库(内存数据库或容器)

✅ 测试真实的集成点

✅ 清理测试数据

❌ 避免测试UI层

❌ 不要测试外部服务的内部逻辑

对于 ST:

✅ 模拟真实用户场景

✅ 包含性能和安全测试

✅ 在不同环境中测试

❌ 避免过多的E2E测试

❌ 不要依赖不稳定的外部服务

对于整个测试策略:

  • 自动化一切可以自动化的测试
  • 保持测试快速反馈
  • 测试应该在CI/CD中自动运行
  • 测试代码和产品代码同等重要
  • 定期重构和维护测试代码

记住:UT是基础,IT是桥梁,ST是保障。良好的测试策略应该平衡这三者,形成稳定的测试金字塔。

相关推荐
灰阳阳4 个月前
替身演员的艺术:pytest-mock 从入门到飙戏
自动化测试·python·pytest·unit testing·pytest-mock
散人10247 个月前
Android Test3 获取的ANDROID_ID值不同
android·unit testing
Lossya1 年前
【python实操】python小程序之UnitTest框架以及TestSuite书写方法
开发语言·python·小程序·继承·封装·unit testing
Maer091 年前
Typescript 使用 Jest 进行单元测试
javascript·typescript·unit testing
G皮T2 年前
【单元测试】Spring Boot 的测试库
spring boot·单元测试·unit testing·unit test
code-jam2 年前
springboot项目,@Test写法 @Before @After
spring boot·单元测试·unit testing
知识的宝藏2 年前
如何从命令行运行testng.xml?
unit testing
老马啸西风2 年前
test-02-test case generate 测试用例生成 EvoSuite 介绍
java·开发语言·junit·开源·测试用例·unit testing
老马啸西风2 年前
test fuzz-04-模糊测试 jazzer Coverage-guided, in-process fuzzing for the JVM
开发语言·jvm·单元测试·开源·测试覆盖率·unit testing