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

Selenium/C#测试套件中如何处理Mac上挂起的SafariDriver及残留Safari浏览器实例问题

Selenium/C#测试套件中如何处理Mac上挂起的SafariDriver及残留Safari浏览器实例问题

我太懂这种糟心的情况了——Safari死死限制单实例,加上WebDriver偶尔“掉链子”没彻底关掉浏览器,直接导致后续测试卡壳。你用的Driver.Close()和Driver.Quit()只能干掉驱动进程,却碰不到Safari本身,这其实是因为有时候驱动和浏览器的进程关联会意外断裂,驱动的退出命令根本传不到浏览器那边。

给你几个亲测有效的解决方案,按稳妥程度排序:

1. 双重保险:先正常销毁驱动,再强制杀Safari进程

先优化你的清理逻辑,确保驱动资源被彻底释放,再用Mac终端命令强制结束Safari。把下面的方法加到你的AfterScenario里,甚至BeforeScenario开头也可以加一次,从根源杜绝残留:

using System.Diagnostics;

private IWebDriver Driver; // 你的WebDriver实例

public void FullSafariCleanup()
{
    try
    {
        // 第一步:正常销毁驱动实例
        if (Driver != null)
        {
            Driver.Quit();
            Driver.Dispose();
            Driver = null;
        }

        // 第二步:强制关闭所有Safari进程,双重保险
        var killProcess = new ProcessStartInfo
        {
            FileName = "/bin/bash",
            Arguments = "-c \"killall Safari 2>/dev/null\"",
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        using (var process = Process.Start(killProcess))
        {
            process?.WaitForExit();
        }
    }
    catch (Exception ex)
    {
        // 这里可以加日志记录,比如"清理Safari资源失败:" + ex.Message
    }
}

解释下:2>/dev/null是为了避免如果没有Safari进程时终端输出错误信息,让命令执行更安静。

2. 用AppleScript优雅关闭Safari(适合正常响应的情况)

如果不想用强制杀进程的方式,也可以用Mac的AppleScript给Safari发送正常的退出信号,这种方式更“友好”,适合大部分正常场景:

public void GracefullyCloseSafari()
{
    try
    {
        var scriptProcess = new ProcessStartInfo
        {
            FileName = "osascript",
            Arguments = "-e 'tell application \"Safari\" to quit' -e 'delay 1'",
            CreateNoWindow = true,
            UseShellExecute = false
        };

        using (var process = Process.Start(scriptProcess))
        {
            process?.WaitForExit();
        }
    }
    catch (Exception ex)
    {
        // 日志记录异常
    }
}

delay 1是给Safari留一点时间完成退出操作,避免进程还没完全关掉就开始下一个测试。

3. 测试前的前置检查

在BeforeScenario开头加一段检查,确保没有运行中的Safari进程再启动新测试,这样就算之前的测试崩溃了,也不会影响下一次:

public void EnsureNoSafariRunningBeforeTest()
{
    try
    {
        var checkProcess = new ProcessStartInfo
        {
            FileName = "/bin/bash",
            Arguments = "-c \"pgrep Safari\"",
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        using (var process = Process.Start(checkProcess))
        {
            process?.WaitForExit();
            var output = process?.StandardOutput.ReadToEnd();
            if (!string.IsNullOrEmpty(output))
            {
                // 如果有Safari进程,先杀掉
                KillSafariProcesses();
            }
        }
    }
    catch (Exception ex)
    {
        // 日志记录
    }
}

// 复用之前的KillSafariProcesses方法
private void KillSafariProcesses()
{
    var killProcess = new ProcessStartInfo
    {
        FileName = "/bin/bash",
        Arguments = "-c \"killall Safari 2>/dev/null\"",
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        UseShellExecute = false,
        CreateNoWindow = true
    };

    using (var process = Process.Start(killProcess))
    {
        process?.WaitForExit();
    }
}

最后提个小注意:如果你的测试是在CI/CD环境(比如Mac上的Jenkins)运行,要确保执行测试的用户有足够权限执行这些终端命令,一般本地测试的普通用户权限就够了。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 12:59:29