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

Electron Playwright测试因Flask后端导致挂起

Electron Playwright测试因Flask后端导致挂起

兄弟,我之前踩过一模一样的坑!Electron里先启动Flask后端再开窗口,用Playwright做自动化测试的时候老是挂起,试了好几种方法才搞定,给你分享下我的解决思路:

首先先把我当时的Electron核心代码贴出来(和你的场景几乎一致):

const { app, BrowserWindow } = require('electron');
const { spawn } = require('child_process');
const path = require("path");

// 路径配置
const rootDirectory = path.join(__dirname, "..","..","..","..")
const pagesDirectory = path.join(rootDirectory, "frontend", "pages")
let flaskProcess;

app.whenReady().then(async () => {
  // 先启动Flask后端
  flaskProcess = spawn('python', [path.join(rootDirectory, 'backend', 'app.py')], {
    stdio: 'inherit' // 这里是第一个坑!
  });

  // 原来用固定延时等后端启动,很不稳定
  await new Promise(resolve => setTimeout(resolve, 2000));
  
  // 打开主窗口
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true
    }
  });

  await mainWindow.loadFile(path.join(pagesDirectory, 'index.html'));
});

// 关闭app前杀后端进程
app.on('before-quit', (event) => {
  if (flaskProcess) {
    flaskProcess.kill(); // 这里是第二个坑!
  }
});

问题根源分析

Playwright测试挂起90%的原因是Electron应用没有被正确终止,要么是Flask子进程还在后台跑,要么是Playwright没等到应用退出的信号,具体到我们的场景:

  1. stdio: 'inherit'会让Flask的输出流绑定到Electron的主进程流,Playwright会一直监听这些流,只要流没关闭就不会认为应用退出;
  2. 单纯用flaskProcess.kill()可能杀不干净Flask的子进程(比如Flask开了调试模式会自动fork进程);
  3. 固定延时等后端启动不可靠,有时候后端还没就绪,窗口已经打开,测试逻辑提前执行导致后续流程卡住。

逐个解决的办法

  • 改掉stdio配置:测试环境下别用inherit,换成['ignore', 'pipe', 'pipe'],让子进程的输出和主进程解耦,这样Electron退出时流能正常关闭:

    flaskProcess = spawn('python', [path.join(rootDirectory, 'backend', 'app.py')], {
      stdio: ['ignore', 'pipe', 'pipe'],
      env: { ...process.env, FLASK_ENV: process.env.TEST_MODE ? 'production' : 'development' }
    });
    

    顺便在测试模式下把Flask改成生产模式,避免调试模式的fork行为。

  • 彻底杀死Flask进程树:用tree-kill包(先npm install tree-kill)来杀死整个进程树,确保没有残留的Flask进程:

    const treeKill = require('tree-kill');
    
    app.on('before-quit', (event) => {
      if (flaskProcess) {
        treeKill(flaskProcess.pid);
        flaskProcess = null;
      }
    });
    
  • 用主动检测代替固定延时:在Electron里等后端真正就绪再开窗口,比如发请求检测health接口:

    const fetch = require('node-fetch');
    
    // 封装一个等后端就绪的函数
    async function waitForBackendReady() {
      const maxRetries = 10;
      let retries = 0;
      while (retries < maxRetries) {
        try {
          const res = await fetch('http://localhost:5000/health');
          if (res.ok) break;
        } catch (err) {
          // 后端还没起来,继续等
          await new Promise(resolve => setTimeout(resolve, 500));
          retries++;
        }
      }
    }
    
    app.whenReady().then(async () => {
      flaskProcess = spawn('python', [path.join(rootDirectory, 'backend', 'app.py')], {
        stdio: ['ignore', 'pipe', 'pipe'],
        env: { ...process.env, FLASK_ENV: process.env.TEST_MODE ? 'production' : 'development' }
      });
    
      // 等后端真正就绪
      await waitForBackendReady();
      
      // 再开窗口
      const mainWindow = new BrowserWindow({...});
      await mainWindow.loadFile(...);
    });
    
  • 给Playwright测试加保险:在Playwright配置里设置超时,并且测试结束后主动关闭应用,别等它自己退出:

    // playwright.config.js
    module.exports = {
      use: {
        timeout: 30000, // 全局超时30秒
      },
      electron: {
        timeout: 30000,
        launchOptions: {
          env: { ...process.env, TEST_MODE: '1' } // 告诉Electron现在是测试模式
        }
      }
    };
    

    测试代码里主动关闭应用:

    const { test, expect } = require('@playwright/test');
    
    test('Electron app with Flask backend', async ({ electron }) => {
      const app = await electron.launch({ args: ['.'] });
      const window = await app.firstWindow();
      
      // 测试逻辑,比如检查页面标题
      await expect(window.title()).toBe('My App');
      
      // 测试完主动关闭,别等Playwright自己处理
      await app.close();
    });
    

最后再提个小细节

如果你的Flask用了debug=True,测试模式下一定要关掉,因为调试模式会自动重启进程,很容易导致Electron无法正确杀死它,直接在启动命令里设置FLASK_ENV=production或者在代码里判断测试模式禁用调试。

备注:内容来源于stack exchange,提问作者user24995271

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 16:38:12