[{"data":1,"prerenderedAt":499},["ShallowReactive",2],{"content:\u002Fposts\u002F2025\u002Ffrontend-testing-guide-10-essential-rules-for-naming-tests":3,"surround:\u002Fposts\u002F2025\u002Ffrontend-testing-guide-10-essential-rules-for-naming-tests":488},{"id":4,"title":5,"body":6,"canonical":19,"categories":460,"date":462,"description":463,"draft":464,"extension":465,"image":466,"meta":467,"navigation":362,"path":471,"permalink":472,"readingTime":473,"recommend":478,"references":472,"seo":479,"sitemap":480,"stem":481,"tags":482,"type":472,"updated":486,"__hash__":487},"content\u002Fposts\u002F2025\u002FFrontend Testing Guide - 10 Essential Rules for Naming Tests.md","【翻译】前端测试指南：命名测试的 10 条基本规则",{"type":7,"value":8,"toc":443},"minimark",[9,23,26,29,42,45,68,71,76,79,91,98,104,108,111,117,123,128,132,135,141,147,149,155,159,162,168,174,180,184,187,193,199,204,208,211,217,223,228,232,235,241,247,252,256,259,265,271,276,280,283,289,295,300,304,307,313,319,321,327,330,333,339,345,348,351,401,404,407,418,421,432,440],[10,11,12],"auths-alex",{},[13,14,15,16],"p",{},"原文地址：",[17,18,22],"a",{"href":19,"rel":20},"https:\u002F\u002Falexop.dev\u002Fposts\u002Ffrontend-testing-guide-10-essential-rules\u002F",[21],"nofollow","Frontend Testing Guide: 10 Essential Rules for Naming Tests",[24,25],"hr",{},[13,27,28],{},"更好的测试之路始于一些非常简单的事情：如何命名测试。好的测试名称：",[30,31,32,36,39],"ol",{},[33,34,35],"li",{},"使您的测试套件更易于维护",[33,37,38],{},"指导您编写关注用户行为的测试",[33,40,41],{},"提高团队的清晰度和可读性",[13,43,44],{},"在这篇博文中，我们将探讨编写更好的测试的 10 条基本规则，这些规则将改变您的测试方法。这些原则是：",[30,46,47,50,53],{},[33,48,49],{},"与框架无关",[33,51,52],{},"适用于整个测试金字塔",[33,54,55,56],{},"适用于各种测试工具：\n",[57,58,59,62,65],"ul",{},[33,60,61],{},"单元测试（Jest、Vitest）",[33,63,64],{},"集成测试",[33,66,67],{},"端到端测试（Cypress、Playwright）",[13,69,70],{},"通过遵循这些规则，无论您选择什么测试框架或方法，您都将创建更强大且更易于理解的测试套件。",[72,73,75],"h2",{"id":74},"_1-使用使用-shoule-动词","1. 使用使用 'shoule' + 动词",[13,77,78],{},"每个测试名称都应以“should”开头，后跟一个动作动词。",[80,81,88],"pre",{"className":82,"code":84,"filename":85,"language":86,"meta":87},[83],"language-ts","it('displays the error message', () => {})\nit('modal visibility', () => {})\nit('form validation working', () => {})\n","Bad","ts","",[89,90,84],"code",{"__ignoreMap":87},[80,92,96],{"className":93,"code":94,"filename":95,"language":86,"meta":87},[83],"it('should displays the error message when validation fails', () => {})\nit('should show modal when trigger button is clicked', () => {})\nit('should validate form when user submits', () => {})\n","Good",[89,97,94],{"__ignoreMap":87},[13,99,100,101],{},"通用模式：",[89,102,103],{"code":103},"should 动词 额外说明",[72,105,107],{"id":106},"_2-包含触发事件","2. 包含触发事件",[13,109,110],{},"指定导致您正在测试的行为的原因。",[80,112,115],{"className":113,"code":114,"filename":85,"language":86,"meta":87},[83],"it('should update counter', () => {})\nit('should validate email', () => {})\nit('should show dropdown', () => {})\n",[89,116,114],{"__ignoreMap":87},[80,118,121],{"className":119,"code":120,"filename":95,"language":86,"meta":87},[83],"it('should increment counter when plus button is clicked', () => {})\nit('should show error when email format is invalid', () => {})\nit('should open dropdown when toggle is clicked', () => {})\n",[89,122,120],{"__ignoreMap":87},[13,124,100,125],{},[89,126,127],{"code":127},"should 动词 额外说明 when 操作事件",[72,129,131],{"id":130},"_3-使用描述性上下文对相关测试进行分组","3. 使用描述性上下文对相关测试进行分组",[13,133,134],{},"使用描述块创建清晰的测试层次结构。",[80,136,139],{"className":137,"code":138,"filename":85,"language":86,"meta":87},[83],"describe('AuthForm', () => {\n    it('should test empty state', () => {})\n    it('should test invalid state', () => {})\n    it('should test success state', () => {})\n})\n",[89,140,138],{"__ignoreMap":87},[80,142,145],{"className":143,"code":144,"filename":95,"language":86,"meta":87},[83],"describe('AuthForm', () => {\n    describe('when form is empty', () => {\n        it('should disable submit button', () => {})\n        it('should not show any validation errors', () => {})\n    })\n\n    describe('when submitting invalid data', () => {\n        it('should show validation errors', () => {})\n        it('should keep submit button disabled', () => {})\n    })\n})\n",[89,146,144],{"__ignoreMap":87},[13,148,100],{},[80,150,153],{"className":151,"code":152,"language":86,"meta":87},[83],"describe('[Component\u002FFeature]', () => {\n    describe('when [specific condition]', () => {\n        it('should [expected behavior]', () => {})\n    })\n})\n",[89,154,152],{"__ignoreMap":87},[72,156,158],{"id":157},"_4-明确命名状态更改","4. 明确命名状态更改",[13,160,161],{},"在测试名称中清楚地描述之前和之后的状态。",[80,163,166],{"className":164,"code":165,"filename":85,"language":86,"meta":87},[83],"it('should change status', () => {})\nit('should update todo', () => {})\nit('should modify permissions', () => {})\n",[89,167,165],{"__ignoreMap":87},[80,169,172],{"className":170,"code":171,"filename":95,"language":86,"meta":87},[83],"it('should change status from pending to approved', () => {})\nit('should mark todo as completed when checkbox clicked', () => {})\nit('should upgrade user from basic to premium', () => {})\n",[89,173,171],{"__ignoreMap":87},[13,175,176,177],{},"通用模式： ",[89,178,179],{"code":179},"should change [属性-attribute] from [初始状态] to [结束状态]",[72,181,183],{"id":182},"_5-清楚地描述异步行为","5. 清楚地描述异步行为",[13,185,186],{},"包括异步操作的加载和结果状态。",[80,188,191],{"className":189,"code":190,"filename":85,"language":86,"meta":87},[83],"it('should load data', () => {})\nit('should handle API call', () => {})\nit('should fetch user', () => {})\n",[89,192,190],{"__ignoreMap":87},[80,194,197],{"className":195,"code":196,"filename":95,"language":86,"meta":87},[83],"it('should show skeleton while loading data', () => {})\nit('should display error message when API call fails', () => {})\nit('should render profile after user data loads', () => {})\n",[89,198,196],{"__ignoreMap":87},[13,200,176,201],{},[89,202,203],{"code":203},"should [verb] [expected outcome] [during\u002Fafter] [async operation]",[72,205,207],{"id":206},"_6-命名中明确错误案例","6. 命名中明确错误案例",[13,209,210],{},"明确错误的类型及其原因",[80,212,215],{"className":213,"code":214,"filename":85,"language":86,"meta":87},[83],"it('should show error', () => {})\nit('should handle invalid input', () => {})\nit('should validate form', () => {})\n",[89,216,214],{"__ignoreMap":87},[80,218,221],{"className":219,"code":220,"filename":95,"language":86,"meta":87},[83],"it('should show \"Invalid Card\" when card number is wrong', () => {})\nit('should display \"Required\" when password is empty', () => {})\nit('should show network error when API is unreachable', () => {})\n",[89,222,220],{"__ignoreMap":87},[13,224,176,225],{},[89,226,227],{"code":227},"should show [specific error message] when [error condition]",[72,229,231],{"id":230},"_7使用商业语言而不是技术术语","7：使用商业语言，而不是技术术语",[13,233,234],{},"使用领域语言而不是实现细节编写测试。",[80,236,239],{"className":237,"code":238,"filename":85,"language":86,"meta":87},[83],"it('should update state', () => {})\nit('should dispatch action', () => {})\nit('should modify DOM', () => {})\n",[89,240,238],{"__ignoreMap":87},[80,242,245],{"className":243,"code":244,"filename":95,"language":86,"meta":87},[83],"it('should save customer order', () => {})\nit('should update cart total', () => {})\nit('should mark order as delivered', () => {})\n",[89,246,244],{"__ignoreMap":87},[13,248,176,249],{},[89,250,251],{"code":251},"should [business action] [business entity]",[72,253,255],{"id":254},"_8包括重要的先决条件","8：包括重要的先决条件",[13,257,258],{},"指定影响正在测试的行为的条件。",[80,260,263],{"className":261,"code":262,"filename":85,"language":86,"meta":87},[83],"it('should enable button', () => {})\nit('should show message', () => {})\nit('should apply discount', () => {})\n",[89,264,262],{"__ignoreMap":87},[80,266,269],{"className":267,"code":268,"filename":95,"language":86,"meta":87},[83],"it('should enable checkout when cart has items', () => {})\nit('should show free shipping when total exceeds $100', () => {})\nit('should apply discount when user is premium member', () => {})\n",[89,270,268],{"__ignoreMap":87},[13,272,176,273],{},[89,274,275],{"code":275},"should [expected behavior] when [precondition]",[72,277,279],{"id":278},"_9从用户角度命名-ui-反馈测试","9：从用户角度命名 UI 反馈测试",[13,281,282],{},"描述用户感知到的视觉变化。",[80,284,287],{"className":285,"code":286,"filename":85,"language":86,"meta":87},[83],"it('should set error class', () => {})\nit('should toggle visibility', () => {})\nit('should update styles', () => {})\n",[89,288,286],{"__ignoreMap":87},[80,290,293],{"className":291,"code":292,"filename":95,"language":86,"meta":87},[83],"it('should highlight search box in red when empty', () => {})\nit('should show green checkmark when password is strong', () => {})\nit('should disable submit button while processing', () => {})\n",[89,294,292],{"__ignoreMap":87},[13,296,176,297],{},[89,298,299],{"code":299},"should [visual change] when [user action\u002Fcondition]",[72,301,303],{"id":302},"_10逐步构建复杂的工作流程","10：逐步构建复杂的工作流程",[13,305,306],{},"将复杂的流程分解为清晰的步骤。",[80,308,311],{"className":309,"code":310,"filename":85,"language":86,"meta":87},[83],"describe('Checkout', () => {\n    it('should process checkout', () => {})\n    it('should handle shipping', () => {})\n    it('should complete order', () => {})\n})\n",[89,312,310],{"__ignoreMap":87},[80,314,317],{"className":315,"code":316,"filename":95,"language":86,"meta":87},[83],"describe('Checkout Process', () => {\n    it('should first validate items are in stock', () => {})\n    it('should then collect shipping address', () => {})\n    it('should finally process payment', () => {})\n\n    describe('after successful payment', () => {\n        it('should display order confirmation', () => {})\n        it('should send confirmation email', () => {})\n    })\n})\n",[89,318,316],{"__ignoreMap":87},[13,320,100],{},[80,322,325],{"className":323,"code":324,"language":86,"meta":87},[83],"describe('[Complex Process]', () => {\n    it('should first [initial step]', () => {})\n    it('should then [next step]', () => {})\n    it('should finally [final step]', () => {})\n\n    describe('after [key milestone]', () => {\n        it('should [follow-up action]', () => {})\n    })\n})\n",[89,326,324],{"__ignoreMap":87},[72,328,329],{"id":329},"完整示例",[13,331,332],{},"这是一个综合示例，展示了如何组合所有这些规则：",[80,334,337],{"className":335,"code":336,"filename":85,"language":86,"meta":87},[83],"describe('ShoppingCart', () => {\n    it('test adding item', () => {})\n    it('check total', () => {})\n    it('handle checkout', () => {})\n})\n",[89,338,336],{"__ignoreMap":87},[80,340,343],{"className":341,"code":342,"filename":95,"language":86,"meta":87},[83],"describe('ShoppingCart', () => {\n    describe('when adding items', () => {\n        it('should add item to cart when add button is clicked', () => {})\n        it('should update total price immediately', () => {})\n        it('should show item count badge', () => {})\n    })\n\n    describe('when cart is empty', () => {\n        it('should display empty cart message', () => {})\n        it('should disable checkout button', () => {})\n    })\n\n    describe('during checkout process', () => {\n        it('should validate stock before proceeding', () => {})\n        it('should show loading indicator while processing payment', () => {})\n        it('should display success message after completion', () => {})\n    })\n})\n",[89,344,342],{"__ignoreMap":87},[72,346,347],{"id":347},"测试名称清单",[13,349,350],{},"在提交测试之前，请验证其名称：",[57,352,355,365,371,377,383,389,395],{"className":353},[354],"contains-task-list",[33,356,359,364],{"className":357},[358],"task-list-item",[360,361],"input",{"disabled":362,"type":363},true,"checkbox"," 以 \"should\" 开头",[33,366,368,370],{"className":367},[358],[360,369],{"disabled":362,"type":363}," 使用明确的动作动词",[33,372,374,376],{"className":373},[358],[360,375],{"disabled":362,"type":363}," 指定触发条件",[33,378,380,382],{"className":379},[358],[360,381],{"disabled":362,"type":363}," 使用商务语言",[33,384,386,388],{"className":385},[358],[360,387],{"disabled":362,"type":363}," 描述可见的行为",[33,390,392,394],{"className":391},[358],[360,393],{"disabled":362,"type":363}," 足够具体以供调试",[33,396,398,400],{"className":397},[358],[360,399],{"disabled":362,"type":363}," 与相关测试进行逻辑分组",[72,402,403],{"id":403},"结论",[13,405,406],{},"深思熟虑的测试命名是编写更好测试的更广泛领域的基本组成部分。为了保持整个团队的一致性：",[30,408,409,412,415],{},[33,410,411],{},"详细记录您的命名约定",[33,413,414],{},"与所有团队成员分享这些准则",[33,416,417],{},"将指南集成到您的开发工作流程中",[13,419,420],{},"对于使用 GitHub Copilot 等 AI 工具的团队：",[30,422,423,426,429],{},[33,424,425],{},"将这些指南纳入您的项目文档中",[33,427,428],{},"将包含这些规则的 markdown 文件链接到 Copilot",[33,430,431],{},"这种集成允许 Copilot 建议符合您约定的测试名称",[13,433,434,435],{},"有关将文档链接到 Copilot 的更多信息，请参阅： ",[17,436,439],{"href":437,"rel":438},"https:\u002F\u002Fvisualstudiomagazine.com\u002FArticles\u002F2024\u002F09\u002F09\u002FVS-Code-Experiments-Boost-AI-Copilot-Functionality.aspx",[21],"VS Code 实验增强了 AI Copilot 功能",[13,441,442],{},"通过执行这些步骤，您可以确保整个项目的测试命名保持一致、高质量。",{"title":87,"searchDepth":444,"depth":444,"links":445},4,[446,448,449,450,451,452,453,454,455,456,457,458,459],{"id":74,"depth":447,"text":75},2,{"id":106,"depth":447,"text":107},{"id":130,"depth":447,"text":131},{"id":157,"depth":447,"text":158},{"id":182,"depth":447,"text":183},{"id":206,"depth":447,"text":207},{"id":230,"depth":447,"text":231},{"id":254,"depth":447,"text":255},{"id":278,"depth":447,"text":279},{"id":302,"depth":447,"text":303},{"id":329,"depth":447,"text":329},{"id":347,"depth":447,"text":347},{"id":403,"depth":447,"text":403},[461],"译","2025-01-10 14:31:21","更好的测试之路始于一些非常简单的事情。",false,"md","https:\u002F\u002Fbitmc.uno\u002Fpicgo\u002FFrontend%20Testing%20Guide%20-%2010%20Essential%20Rules%20for%20Naming%20Tests.jpg",{"aside":468},[469,470],"toc","auth-alex","\u002Fposts\u002F2025\u002Ffrontend-testing-guide-10-essential-rules-for-naming-tests",null,{"text":474,"minutes":475,"time":476,"words":477},"8 min read",7.545,452700,1509,1,{"title":5,"description":463},{"loc":471},"posts\u002F2025\u002FFrontend Testing Guide - 10 Essential Rules for Naming Tests",[483,484,485],"测试","前端","指南","2026-02-07 23:23:50","gHiguxWgKvPdjBPXinDLGIdzpZIfkP4kk8JsKHgeL1U",[489,494],{"title":490,"path":491,"stem":492,"date":493,"type":472,"children":-1},"【翻译】Vue 3 中的动态 Pinia Store","\u002Fposts\u002F2025\u002Fvue3-dynamic-pinia-store","posts\u002F2025\u002Fvue3-dynamic-pinia-store","2025-01-10 14:14:59",{"title":495,"path":496,"stem":497,"date":498,"type":472,"children":-1},"【翻译】使用 Vitest 测试 Vue 组件","\u002Fposts\u002F2025\u002Ftesting-vue-components-with-vitest","posts\u002F2025\u002Ftesting vue components with vitest","2025-01-14 10:12:32",1789642585732]