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

Codeception验收测试:如何检测JS函数调用或AJAX执行?

针对你的问题,我整理了几个无需代理、适配你当前Selenium+ChromeDriver环境的可行方案:


方案1:注入JS监听目标函数调用(推荐,直接满足你检查log.execute()是否执行的需求)

Codeception的Acceptance测试支持直接执行JS,我们可以通过重写目标函数的方式添加调用标记,之后在测试中验证这个标记:

$I = new AcceptanceTester($scenario);
$I->amOnUrl('http://example.com');

// 等待log对象加载完成(避免页面未完全初始化就执行注入)
$I->waitForJS("return typeof window.log !== 'undefined';", 5);

// 注入JS包装原函数,添加调用标记
$I->executeJS("
  // 保存原始的execute方法
  window._originalLogExecute = window.log.execute;
  // 初始化调用标记
  window.logExecuteWasCalled = false;
  // 重写execute方法,执行时标记为已调用
  window.log.execute = function() {
    window.logExecuteWasCalled = true;
    // 调用原方法保证业务逻辑正常执行
    return window._originalLogExecute.apply(this, arguments);
  };
");

// 如果你需要触发某些操作才会调用log.execute(),在这里添加触发步骤
// 比如 $I->click('#some-button');

// 检查标记是否为true,确认函数被执行
$wasCalled = $I->executeJS("return window.logExecuteWasCalled;");
$I->assertTrue($wasCalled, 'log.execute() 未被执行');

这个方法的优势是直接监听函数调用行为,不管AJAX请求是否成功,只要函数被执行就能检测到,完美匹配你的需求。


方案2:通过ChromeDriver获取网络日志验证AJAX请求

如果你更关心AJAX请求是否实际发送,可以利用ChromeDriver的性能日志功能,筛选目标请求:

  1. 先修改Codeception的acceptance.suite.yml配置,启用性能日志:
modules:
  enabled:
    - WebDriver:
        url: 'http://example.com'
        browser: chrome
        capabilities:
          goog:chromeOptions:
            args: ["--enable-logging"]
          loggingPrefs:
            performance: 'ALL'
  1. 在测试中获取并分析日志:
$I = new AcceptanceTester($scenario);
$I->amOnUrl('http://example.com');

// 等待页面加载完成,确保AJAX请求已发送
$I->wait(2);

// 获取性能日志
$logs = $I->getDriver()->manage()->getLog('performance');
$targetAjaxFound = false;

foreach ($logs as $logEntry) {
    $logData = json_decode($logEntry['message'], true);
    $request = $logData['message']['params']['request'] ?? [];
    
    // 替换成你的AJAX请求的特征(比如URL包含特定路径)
    if (!empty($request['url']) && strpos($request['url'], '/your-ajax-endpoint-path') !== false) {
        $targetAjaxFound = true;
        break;
    }
}

$I->assertTrue($targetAjaxFound, '目标AJAX请求未发送');

这个方法不需要修改页面JS,但需要你知道AJAX请求的具体特征(比如URL)。


方案3:换用PHPUnit + Facebook WebDriver直接操作

如果你觉得Codeception的封装不够灵活,可以直接用PHPUnit搭配官方的Selenium PHP绑定(Facebook WebDriver),逻辑和方案1类似:

use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use PHPUnit\Framework\TestCase;

class LogExecuteTest extends TestCase {
    protected RemoteWebDriver $driver;

    protected function setUp(): void {
        // 配置ChromeDriver启用日志(如果用方案2的话需要加)
        $options = new ChromeOptions();
        $capabilities = DesiredCapabilities::chrome();
        
        $this->driver = RemoteWebDriver::create(
            'http://localhost:4444/wd/hub', // Selenium服务地址
            $capabilities
        );
    }

    public function testLogExecuteIsCalled(): void {
        $this->driver->get('http://example.com');
        
        // 等待log对象加载
        $this->driver->wait(5)->until(function ($driver) {
            return $driver->executeScript("return typeof window.log !== 'undefined';");
        });

        // 注入监听JS
        $this->driver->executeScript("
            window.logExecuteCalled = false;
            const original = window.log.execute;
            window.log.execute = function() {
                window.logExecuteCalled = true;
                return original.apply(this, arguments);
            };
        ");

        // 检查调用标记
        $wasCalled = $this->driver->executeScript("return window.logExecuteCalled;");
        $this->assertTrue($wasCalled);
    }

    protected function tearDown(): void {
        $this->driver->quit();
    }
}

注意事项

  • 如果log对象是页面异步加载生成的,一定要用waitForJS等待对象初始化完成后再注入监听代码;
  • 网络日志方案需要确保ChromeDriver版本和Chrome浏览器版本兼容,避免日志无法正常获取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:13:28