{"componentChunkName":"component---src-templates-docs-js","path":"/docs/testing-environments.html","result":{"data":{"markdownRemark":{"html":"<!-- 本文档适用于那些熟悉 JavaScript 并且可能已经使用它编写过测试的人。它可以作为 React 组件测试环境差异的参考，以及这些差异会如何影响他们编写的测试。本文档倾向基于 Web 的 react-dom 组件的测试，但也有基于其他渲染器测试的注释。 -->\n<p>本章节介绍了可能会影响你测试环境的因素，并包含某些场景下的建议。</p>\n<h3 id=\"test-runners\"><a href=\"#test-runners\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>测试运行器 </h3>\n<p>使用 <a href=\"https://jestjs.io/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Jest</a>，<a href=\"https://mochajs.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">mocha</a>，<a href=\"https://github.com/avajs/ava\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ava</a> 等测试运行器能像编写 JavaScript 一样编写测试套件，并将其作为开发过程的环节运行。此外，测试套件也将作为持续集成的环节运行。</p>\n<ul>\n<li>Jest 与 React 项目广泛兼容，支持诸如模拟 <a href=\"#mocking-modules\">模块</a>、<a href=\"#mocking-timers\">计时器</a> 和 <a href=\"#mocking-a-rendering-surface\"><code class=\"gatsby-code-text\">jsdom</code></a> 等特性。<strong>如果你使用 Create React App，<a href=\"https://facebook.github.io/create-react-app/docs/running-tests\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Jest 已经能够开箱即用</a>且包含许多实用的默认配置。</strong></li>\n<li>像 <a href=\"https://mochajs.org/#running-mocha-in-the-browser\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">mocha</a> 这样的库在真实浏览器环境下运行良好，并且可以为明确需要它的测试提供帮助。</li>\n<li>端对端测试用于测试跨多个页面的长流程，并且需要<a href=\"#end-to-end-tests-aka-e2e-tests\">不同的设置</a>。</li>\n</ul>\n<h3 id=\"mocking-a-rendering-surface\"><a href=\"#mocking-a-rendering-surface\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>模拟渲染表面 </h3>\n<p>测试通常在无法访问真实渲染表面（如浏览器）的环境中运行。对于这些环境，我们建议使用 <a href=\"https://github.com/jsdom/jsdom\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">jsdom</code></a> 来模拟浏览器，这是一个在 Node.js 内运行的轻量级浏览器实现。</p>\n<p>在大多数情况下，jsdom 的行为类似于常规浏览器，但不具备如<a href=\"https://github.com/jsdom/jsdom#unimplemented-parts-of-the-web-platform\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">布局和导航</a>的功能。这对于大多数基于 Web 的组件测试仍然有用，因为它的运行比为每个测试启动浏览器的方式效率更高。并且由于它与你编写的测试运行在同一个进程中，所以你能够编写代码来检查和断言渲染的 DOM。</p>\n<p>就像在真实的浏览器中一样，jsdom 让我们模拟用户交互；测试可以在 DOM 节点上派发事件，然后观察并断言这些操作的副作用<a href=\"/docs/testing-recipes.html#events\"><small>(例子)</small></a>。</p>\n<p>可以使用上述设置编写大部分 UI 测试：使用 Jest 作为测试运行器，渲染到 jsdom，使用 <code class=\"gatsby-code-text\">act()</code> 辅助函数<a href=\"/docs/testing-recipes.html\"><small>(例子)</small></a>提供的能力通过一系列的浏览器事件来模拟用户交互行为。例如，大量 React 自己的测试都是用这种组合编写的。</p>\n<p>如果您正在编写一个主要测试浏览器特定行为的库，并且需要布局或真实输入等原生浏览器行为，那么你可以使用像 <a href=\"https://mochajs.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">mocha</a> 这样的框架。</p>\n<p>在你 <em>无法</em> 模拟 DOM 环境（例如，在 Node.js 上测试 React Native 组件）的情况下，可以使用 <a href=\"/docs/test-utils.html#simulate\">事件模拟辅助函数</a> 来模拟与元素的交互。或者，你也可以使用 <a href=\"https://testing-library.com/docs/react-native-testing-library/intro\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">@testing-library/react-native</code></a> 中的 <code class=\"gatsby-code-text\">fireEvent</code> 辅助函数。</p>\n<p>诸如 <a href=\"https://www.cypress.io/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Cypress</a>，<a href=\"https://github.com/GoogleChrome/puppeteer\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">puppeteer</a> 和 <a href=\"https://www.seleniumhq.org/projects/webdriver/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">webdriver</a> 等框架对于运行<a href=\"#end-to-end-tests-aka-e2e-tests\">端对端测试</a> 都非常有用。</p>\n<h3 id=\"mocking-functions\"><a href=\"#mocking-functions\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>模拟功能 </h3>\n<p>在编写测试的时候，我们希望模拟代码在测试环境较真实环境中缺失的等效部分（例如，在 Node.js 中检查 <code class=\"gatsby-code-text\">navigator.onLine</code> 的状态）。测试还可以监视某些功能，并观察测试的其他部分如何与它们进行交互。有选择的将这些功能模拟为测试友好的版本是很有用的。</p>\n<p>这对于数据获取尤其有用。通常最好使用“假”数据进行测试，以避免从实际 API 端获取数据可能导致的缓慢和不稳定<a href=\"/docs/testing-recipes.html#data-fetching\"><small>（例子）</small></a>。这样做有助于让测试变得可预测。像 <a href=\"https://jestjs.io/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Jest</a> 与 <a href=\"https://sinonjs.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">sinon</a> 这样的类库，支持模拟功能。对于端对端测试，虽然模拟网络可能更加困难，但你可能还想对真实的 API 端进行测试。</p>\n<h3 id=\"mocking-modules\"><a href=\"#mocking-modules\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>模拟模块 </h3>\n<p>一些组件可能会依赖在测试环境中无法正常运行的模块，或者说这些模块对于我们的测试并不必要。那么，通过选择性地模拟来替换这些模块是很有用的<a href=\"/docs/testing-recipes.html#mocking-modules\"><small>（例子）</small></a>。</p>\n<p>在 Node.js 中，测试运行器如 Jest <a href=\"https://jestjs.io/docs/en/manual-mocks\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">支持模拟模块</a>。你也可以使用像 <a href=\"https://www.npmjs.com/package/mock-require\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">mock-require</code></a> 这样的类库。</p>\n<h3 id=\"mocking-timers\"><a href=\"#mocking-timers\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>模拟计时器 </h3>\n<p>组件可能会使用基于时间的函数如 <code class=\"gatsby-code-text\">setTimeout</code>、<code class=\"gatsby-code-text\">setInterval</code> 和 <code class=\"gatsby-code-text\">Date.now</code> 等。在测试环境中，使用可以手动“推进”时间的替代物来模拟这些功能会很有帮助。它会确保你的测试快速运行！依赖于计时器的测试仍将按照顺序解析，但会更快<a href=\"/docs/testing-recipes.html#timers\"><small>（例子）</small></a>。大部分测试框架，包括 <a href=\"https://jestjs.io/docs/en/timer-mocks\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Jest</a>、<a href=\"https://sinonjs.org/releases/latest/fake-timers/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">sinon</a> 和 <a href=\"https://github.com/sinonjs/lolex\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">lolex</a> 都允许你在测试中模拟计时器。</p>\n<p>有些时候可能你不想要模拟计时器。例如，在你测试动画时，或是交互端对时间较为敏感的情况下（如 API 访问速率限制器）。具有计时器模拟的库允许你在每个测试/套件上启用或禁用这个功能，因此你可以明确地选择这些测试的运行方式。</p>\n<h3 id=\"end-to-end-tests-aka-e2e-tests\"><a href=\"#end-to-end-tests-aka-e2e-tests\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>端对端测试 </h3>\n<p>端对端测试对于测试更长的工作流程非常有用，特别是当它们对于你的业务（例如付款或注册）特别重要时。对于这些测试，你可能会希望测试真实浏览器如何渲染整个应用、从真实的 API 端获取数据、使用 session 和 cookies 以及在不同的链接间导航等功能。你可能还希望不仅在 DOM 状态上进行断言，而同时也在后端数据上进行校验（例如，验证更新是否已经在数据库中持久化）。</p>\n<p>在这种场景下，你可以使用像 <a href=\"https://www.cypress.io/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Cypress</a>，<a href=\"https://playwright.dev\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Playwright</a> 等类似框架或者使用 <a href=\"https://github.com/GoogleChrome/puppeteer\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Puppeteer</a> 这样的库，这样你就可以在多个路由之间导航切换，并且不仅能够在浏览器中对副作用进行断言也能够在后端这么做。</p>","frontmatter":{"title":"测试环境","next":null,"prev":"testing-recipes.html"},"fields":{"path":"content/docs/testing-environments.md","slug":"docs/testing-environments.html"}}},"pageContext":{"slug":"docs/testing-environments.html"}},"staticQueryHashes":[]}