Playwright验证断言不匹配时测试未失败问题排查
问题
我写了一段Playwright测试代码,用来断言结账页面的验证错误消息是否和元素文本匹配,但运行时哪怕有一条预期验证消息不对,测试还是显示通过。我希望验证不匹配时测试能直接失败,请问哪里出错了?
代码如下:
test('Assert validations are present on the checkout page', async ({ page }) => { await page.goto('private'); await page.getByRole('button', { name: 'Headwear' }).click() await page.locator("//a[contains(text(),'Adult')]").click() const productGrid = await page.waitForSelector('div[id="productGrid"]'); const products = await productGrid.$$('div[class="product-card relative w-full"]'); for (const product of products) { const outOfStockLabel = await product.$('div:has-text("Out of stock")'); if (!outOfStockLabel) { await product.click(); break; } } await page.click('#btnAddToCart'); await page.locator("//button[@title='Toggle Basket']//*[name()='svg']").click(); await page.click("#btnCartPopUpCheckout"); await page.click("#pay-button-container"); // Step 2: Assert the validation messages for each field await page.waitForSelector("#error-for-email"); await page.waitForSelector("#error-for-TextField1"); await page.waitForSelector("#error-for-TextField2"); await page.waitForSelector("#error-for-shipping-address1"); await page.waitForSelector("#error-for-TextField4"); await page.waitForSelector("#error-for-TextField5"); await page.waitForSelector("#error-for-number"); await page.waitForSelector("#error-for-expiry"); await page.waitForSelector("#error-for-verification_value"); await page.waitForSelector("#error-for-name"); const emailValidation = await page.$eval('#error-for-email', (element) => element.textContent); const firstNameValidation = await page.$eval('#error-for-TextField1', (element) => element.textContent); const lastNameValidation = await page.$eval('#error-for-TextField2', (element) => element.textContent); const addressValidation = await page.$eval('#error-for-shipping-address1', (element) => element.textContent); const cityValidation = await page.$eval('#error-for-TextField4', (element) => element.textContent); const postcodeValidation = await page.$eval('#error-for-TextField5', (element) => element.textContent); const cardNumberValidation = await page.$eval('#error-for-number', (element) => element.textContent); const expirationDateValidation = await page.$eval('#error-for-expiry', (element) => element.textContent); const securityCodeValidation = await page.$eval('#error-for-verification_value', (element) => element.textContent); const nameOnCardValidation = await page.$eval('#error-for-name', (element) => element.textContent); const expectedValidations = { email: 'Enter an emdail', firstName: 'Enter a first name', lastName: 'Enter a last name', address: 'Enter an address', city: 'Enter a city', postcode: 'Enter a ZIP / postal code', cardNumber: 'Enter a card number', expirationDate: 'Enter a valid expiration date', securityCode: 'Enter the CVV or security code on your card', nameOnCard: "Enter your name exactly as it’s written on your card", }; const validationResults = { email: emailValidation, firstName: firstNameValidation, lastName: lastNameValidation, address: addressValidation, city: cityValidation, postcode: postcodeValidation, cardNumber: cardNumberValidation, expirationDate: expirationDateValidation, securityCode: securityCodeValidation, nameOnCard: nameOnCardValidation, }; let allValidationsPassed = true; for (const field in expectedValidations) { if (validationResults[field] !== expectedValidations[field]) { console.log(`Validation failed for ${field}: Expected "${expectedValidations[field]}", but got "${validationResults[field]}"`); allValidationsPassed = false; } } if (allValidationsPassed) { console.log('All field validations passed!'); } else { console.log('Some field validations failed.'); } })
解决方案
核心问题
你的代码只是通过console.log输出了验证失败的信息,但没有主动抛出断言失败的异常。Playwright的测试只有在遇到未捕获的错误或断言失败时才会标记为失败,单纯的日志输出不会触发测试失败。
修复方式
有两种可靠的修复方案,推荐使用第一种(Playwright官方最佳实践):
方案1:使用Playwright内置的断言API(推荐)
Playwright的expect断言自带重试机制,能避免因元素文本未完全加载导致的误判,且失败时会直接终止测试并给出清晰的错误信息。
修改后的验证部分代码:
const expectedValidations = { email: 'Enter an email', // 修正原代码拼写错误:emdail -> email firstName: 'Enter a first name', lastName: 'Enter a last name', address: 'Enter an address', city: 'Enter a city', postcode: 'Enter a ZIP / postal code', cardNumber: 'Enter a card number', expirationDate: 'Enter a valid expiration date', securityCode: 'Enter the CVV or security code on your card', nameOnCard: "Enter your name exactly as it’s written on your card", }; // 替换原来的多个waitForSelector,提升执行效率 await Promise.all([ page.locator('#error-for-email').waitFor(), page.locator('#error-for-TextField1').waitFor(), page.locator('#error-for-TextField2').waitFor(), page.locator('#error-for-shipping-address1').waitFor(), page.locator('#error-for-TextField4').waitFor(), page.locator('#error-for-TextField5').waitFor(), page.locator('#error-for-number').waitFor(), page.locator('#error-for-expiry').waitFor(), page.locator('#error-for-verification_value').waitFor(), page.locator('#error-for-name').waitFor(), ]); // 直接对每个错误元素断言文本 await expect(page.locator('#error-for-email')).toHaveText(expectedValidations.email); await expect(page.locator('#error-for-TextField1')).toHaveText(expectedValidations.firstName); await expect(page.locator('#error-for-TextField2')).toHaveText(expectedValidations.lastName); await expect(page.locator('#error-for-shipping-address1')).toHaveText(expectedValidations.address); await expect(page.locator('#error-for-TextField4')).toHaveText(expectedValidations.city); await expect(page.locator('#error-for-TextField5')).toHaveText(expectedValidations.postcode); await expect(page.locator('#error-for-number')).toHaveText(expectedValidations.cardNumber); await expect(page.locator('#error-for-expiry')).toHaveText(expectedValidations.expirationDate); await expect(page.locator('#error-for-verification_value')).toHaveText(expectedValidations.securityCode); await expect(page.locator('#error-for-name')).toHaveText(expectedValidations.nameOnCard);
方案2:保留循环逻辑,主动抛出错误
如果你想保留原有的循环校验逻辑,需要在最后判断allValidationsPassed,若为false则主动抛出错误:
let allValidationsPassed = true; const errorMessages = []; for (const field in expectedValidations) { if (validationResults[field] !== expectedValidations[field]) { const errorMsg = `Validation failed for ${field}: Expected "${expectedValidations[field]}", but got "${validationResults[field]}"`; errorMessages.push(errorMsg); console.log(errorMsg); allValidationsPassed = false; } } if (!allValidationsPassed) { throw new Error(`部分验证失败:\n${errorMessages.join('\n')}`); }
额外提示
你原代码里预期的邮箱验证消息存在拼写错误:Enter an emdail 应该是 Enter an email,这会导致验证失败,记得修正。
内容的提问来源于stack exchange,提问作者Amar
相关产品推荐
相关产品推荐

