You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Playwright异步自动化测试:用Winston按测试维度生成有序单日志文件

可行!用Winston实现Playwright测试日志按测试维度集中展示

完全可以实现,核心思路是给每条日志打上测试唯一标识,先暂存所有日志条目,等全部测试执行完毕后,按测试标识聚合再写入文件,就能让每个测试的日志集中展示,而非按时间戳混排。

具体实现步骤

1. 初始化Winston日志实例(内存暂存日志)

先创建一个基于内存传输的Winston实例,用来临时存储所有日志,避免实时写入导致的时间戳混排:

import winston from 'winston';
import { TransportInstance } from 'winston/lib/winston/transports';

// 定义日志结构,包含测试标识
interface TestLogEntry {
  level: string;
  message: string;
  testId: string;
  timestamp: string;
}

// 创建内存传输器
const memoryTransport = new winston.transports.Memory({
  level: 'info'
}) as TransportInstance & { writable: { buffer: TestLogEntry[] } };

// 初始化Winston日志
const logger = winston.createLogger({
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [memoryTransport]
});

2. 给每个测试绑定唯一标识

利用Playwright的测试钩子,在每个测试启动时记录其标题(作为唯一标识),后续所有日志都关联这个标识:

import { test } from '@playwright/test';

test.beforeEach(async ({}, testInfo) => {
  // 将测试标题作为唯一标识,存入测试上下文
  testInfo.testId = testInfo.title;
});

3. 封装带测试标识的日志工具

写一个统一的日志方法,自动给每条日志打上当前测试的标识:

export function logTestMessage(testId: string, level: string, message: string) {
  logger.log({
    level,
    message,
    testId
  });
}

// 在测试中使用示例
test('用户登录测试', async ({ page }, testInfo) => {
  logTestMessage(testInfo.testId, 'info', '开始执行登录测试');
  await page.goto('/login');
  logTestMessage(testInfo.testId, 'debug', '已跳转至登录页');
  // ...测试步骤
});

4. 测试完成后聚合日志并写入文件

在所有测试执行完毕的钩子中,按testId分组日志,然后集中写入文件:

import fs from 'fs/promises';

test.afterAll(async () => {
  // 从内存传输器中取出所有日志条目
  const allLogs = memoryTransport.writable.buffer;
  
  // 按testId分组
  const groupedLogs = allLogs.reduce((acc, log) => {
    if (!acc[log.testId]) {
      acc[log.testId] = [];
    }
    acc[log.testId].push(log);
    return acc;
  }, {} as Record<string, TestLogEntry[]>);

  // 将分组后的日志转为可读性强的格式
  let finalLogContent = '';
  Object.entries(groupedLogs).forEach(([testId, logs]) => {
    finalLogContent += `=== 测试: ${testId} ===\n`;
    logs.forEach(log => {
      finalLogContent += `[${log.timestamp}] ${log.level.toUpperCase()}: ${log.message}\n`;
    });
    finalLogContent += '\n';
  });

  // 写入日志文件
  await fs.writeFile('./test-results/test-logs.log', finalLogContent, 'utf-8');
});

注意事项

  • 40个异步测试的并发执行不会影响日志分组,因为每条日志都绑定了专属的testId,聚合时自动归类
  • 内存暂存日志对40个测试来说完全不会有性能问题,若后续测试量大幅增加,可考虑改用临时文件暂存
  • 可自定义日志格式,比如添加测试状态、执行时长等信息,提升日志可读性

内容的提问来源于stack exchange,提问作者Alon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 09:37:54