Mocha+Selenium测试超时求助:before/after each钩子及用例超时报错
Fixing Mocha + Selenium Timeout Errors in beforeEach/afterEach Hooks and Test Cases
Let's break down exactly what's causing those timeout errors and fix your code step by step. The core issue here is that Mocha isn't being told when your asynchronous hooks and test steps finish, so it hits the timeout waiting for them.
What's Wrong With the Original Code?
- beforeEach Timeout: The
driver.get()call is asynchronous, but you didn't return its promise or use a callback to signal completion to Mocha. Mocha had no way to know when the page load finished, so it waited 50000ms and timed out. - afterEach Timeout: Same problem with
driver.quit()—it's an async operation, but you didn't wait for it to finish. Mocha moved on before the browser closed, triggering the 2000ms timeout. - Test Case Issues: The nested
then()calls created a callback hell that made it hard to track async flow, and thesetTimeout(done, 4000)line used an undefineddonevariable (which would throw an error even if the timeout didn't hit).
Fixed Code with Explanations
Here's the revised code using async/await (the cleanest way to handle async operations in Mocha + Selenium):
var webdriver = require('selenium-webdriver'); var By = require('selenium-webdriver').By; var until = require('selenium-webdriver').until; var test = require('selenium-webdriver/testing'); var fs = require('fs'); var chrome = require('selenium-webdriver/chrome'); var path = require('chromedriver').path; var service = new chrome.ServiceBuilder(path).build(); chrome.setDefaultService(service); var driver = new webdriver.Builder() .withCapabilities(webdriver.Capabilities.chrome()) .build(); test.describe('Test', function() { // Use async/await to wait for page load to finish test.beforeEach(async function() { this.timeout(50000); await driver.get('https://staging.keela.co/login'); }); // Wait for the browser to quit completely before moving on test.afterEach(async function() { await driver.quit(); }); test.it('Test Case', async function() { this.timeout(50000); // Remove the undefined `done` setTimeout - it's unnecessary and error-prone // Wait for email field to exist, then send keys const emailField = await driver.wait(until.elementLocated(By.name('login-email'))); await emailField.sendKeys('bandanakeela@gmail.com'); // Wait for password field, then send keys const passwordField = await driver.wait(until.elementLocated(By.name('login-password'))); await passwordField.sendKeys('123456789'); // Click login button and wait for the action to complete const loginButton = await driver.findElement(By.linkText("Log In")); await loginButton.click(); // Optional: Add a wait for post-login state (e.g., dashboard load) // await driver.wait(until.titleContains('Keela Dashboard')); }); });
Key Fixes Explained
- Async/Await for Hooks: By marking
beforeEachandafterEachasasyncand usingawaiton the Selenium calls, we tell Mocha to wait for those operations to finish before proceeding. No more timeout surprises from unhandled async work. - Flattened Async Flow: Replacing nested
then()calls withawaitmakes the code linear and easy to follow. Each step waits for the previous one to complete, eliminating race conditions. - Removed Invalid
setTimeout: The originalsetTimeout(done, 4000)used an undefineddoneparameter, which would have thrown a runtime error. Selenium's built-in waits are always better than arbitrary delays anyway. - Explicit Element Waits: Using
driver.wait(until.elementLocated(...))ensures we only interact with elements once they exist in the DOM, avoiding "element not found" errors.
Pro Tips to Avoid Future Timeouts
- Always use
await(or return promises) for all async Selenium operations in Mocha tests/hooks. - Use Selenium's
untilconditions to wait for specific states (element visibility, title changes) instead ofsetTimeout—it's more reliable and efficient. - Adjust timeout values only when necessary (e.g., slow staging environments), but prefer fixing async handling over increasing timeouts.
内容的提问来源于stack exchange,提问作者Bandana Singh
相关产品推荐
相关产品推荐

