网站seo规范,公众号设置下载wordpress,网站优化任务,网站建设平台ui确认书在本文中#xff0c;我们将了解如何使用Jest#xff08;Facebook 维护的一个测试框架#xff09;来测试我们的React组件。我们将首先了解如何在纯 JavaScript 函数上使用 Jest#xff0c;然后再了解它提供的一些开箱即用的功能#xff0c;这些功能专门用于使测试 React 应… 在本文中我们将了解如何使用JestFacebook 维护的一个测试框架来测试我们的React组件。我们将首先了解如何在纯 JavaScript 函数上使用 Jest然后再了解它提供的一些开箱即用的功能这些功能专门用于使测试 React 应用程序变得更容易。 值得注意的是Jest 并不是专门针对 React您可以使用它来测试任何 JavaScript 应用程序。然而它提供的一些功能对于测试用户界面来说非常方便这就是为什么它非常适合 React。
应用测试示例
在我们测试任何东西之前我们需要一个应用程序来测试您可以在 GitHub 上找到它以及我们即将编写的所有测试。如果您想使用该应用程序来感受一下您还可以在线找到现场演示。
该应用程序使用 ES2015 编写的使用带有 Babel ES2015 和 React 预设的 webpack 进行编译。我不会详细介绍构建设置但如果您想查看的话一切都在 GitHub 存储库中。您可以在自述文件中找到有关如何在本地运行应用程序的完整说明。如果您想了解更多信息该应用程序是使用webpack构建的我推荐“ Webpack 初学者指南”进行学习。
应用程序的入口是app/index.js render( Todos /, document.getElementById(app) );
该Todos组件是应用程序的主要内容。它包含所有状态该应用程序的硬编码数据实际上可能来自 API 或类似数据并有渲染两个子组件。
因为Todos组件包含所有状态所以每当有任何变化时它需要Todo和AddTodo组件通知它。因此它将函数向下传递到这些组件中当某些数据发生变化时它们可以调用这些函数并Todos可以相应地更新状态。
最后现在您会注意到所有业务逻辑都包含在app/state-functions.js export function toggleDone(todos, id) {…} export function addTodo(todos, todo) {…} export function deleteTodo(todos, id) {…}
如果您熟悉 Redux它们与 Redux 所谓的reducer非常相似。事实上如果这个应用程序变得更大会考虑迁移到 Redux 以获得更明确、结构化的数据方法。
选择 TDD 而不是 TDD
关于测试驱动开发的优缺点已经有很多文章写过了开发人员需要先编写测试然后再编写修复测试的代码。这背后的想法是通过先编写测试您必须思考您正在编写的API并且它可能会导致更好的设计。我认为这在很大程度上取决于个人偏好和测试的类型。我发现对于React组件我喜欢先编写组件然后为最重要的功能添加测试。然而如果您发现先为组件编写测试符合您的工作流程那么您应该这样做。在这里没有硬性规定做适合您和您的团队感觉最好的事情。
什么是Jest
Jest首次发布于2014年尽管它最初引起了很多关注但该项目一度停滞不前并没有得到很积极的开发。然而Facebook投入了大量精力来改进Jest并发布了一些令人印象深刻的变化值得重新考虑。与最初的开源发布相比Jest仅保留了名称和标志。其他一切都已经改变和重写。如果您想了解更多信息可以阅读Christoph Pojer的评论他在其中讨论了该项目的当前状态。
如果您对使用其他框架设置Babel、React和JSX测试感到沮丧那么我强烈建议您尝试Jest。如果您发现现有的测试安装速度很慢我也强烈推荐Jest。它可以自动并行运行测试其watch模式能够运行与更改文件相关的测试这在您拥有大量测试套件时是非常宝贵的。它已经配置了JSDom这意味着您可以编写浏览器测试但通过Node运行它们。它可以处理异步测试并且具有内置的高级功能如mocking、spy和stub。
安装和配置 Jest
首先我们需要安装 Jest。因为我们也在使用 Babel所以我们将安装另外几个模块使 Jest 和 Babel 可以正常使用
npm install --save-dev jest babel-jest babel/core babel/preset-env babel/preset-react您还需要一个babel.config.js包含 Babel 配置的文件以使用您需要的任何预设和插件。如下所示 module.exports { presets: [ babel/preset-env, babel/preset-react, ], };
本文不会深入探讨 Babel 的设置。如果您想具体了解有关 Babel 的更多信息看我以前的文章。
我们还不会安装任何 React 测试工具因为我们不会从测试组件开始而是从测试状态函数开始。
Jest 期望在一个文件夹中找到我们的测试__tests__这已成为 JavaScript 社区中的一种流行惯例我们将在这里坚持这一惯例。如果您不喜欢该__tests__设置开箱即用的 Jest 还支持查找任何.test.js文件.spec.js。
由于我们将测试我们的状态函数因此请继续创建__tests__/state-functions.test.js。 下面是一个测试用例进行测试检查Jest配置是否正常。 describe(Addition, () { it(knows that 2 and 2 make 4, () { expect(2 2).toBe(4); }); });
现在进入您的package.json 添加npm test命令 scripts: { test: jest }
如果您现在执行npm test命令您应该会看到测试运行并通过 PASS __tests__/state-functions.test.js Addition ✓ knows that 2 and 2 make 4 (5ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 passed, 0 total Time: 3.11s
如果您曾经使用过 Jasmine 或其他测试框架Jest允许我们使用describe和it来嵌套测试。您使用多少嵌套取决于您。我喜欢嵌套我的测试这样所有传递给describe和it的描述字符串几乎就像一个句子一样。
当涉及到实际断言时您需要将要测试的内容包装在expect()调用中然后在其上调用断言。在这种情况下我们使用了toBe。您可以在Jest文档中找到所有可用断言的列表。toBe使用来检查给定值是否与测试的值匹配。通过本教程我们将遇到一些Jest的断言。
测试业务逻辑
我们将测试我们的第一个状态函数toggleDone。 toggleDone接收当前状态和我们想要切换的todo的ID。每个todo都有一个完成属性而toggleDone应该将其从true切换为false反之亦然。 注意如果您正在跟随本文确保已经克隆了代码库并将app文件夹复制到包含您的__tests__文件夹的同一目录中。您还需要安装所有应用程序的依赖项例如React。在克隆存储库后运行npm install即可确保全部安装完成。
我将从app/state-functions.js导入函数并设置测试的结构开始。当Jest允许您使用describe和it进行嵌套时您也可以使用test这通常更易于阅读。test只是Jest it函数的别名但有时可以使测试更易于阅读减少嵌套。例如以下是我如何使用嵌套的describe和it调用编写该测试的方法 import { toggleDone } from ../app/state-functions; describe(toggleDone, () { describe(when given an incomplete todo, () { it(marks the todo as completed, () { }); }); });
这是test用法 import { toggleDone } from ../app/state-functions; test(toggleDone completes an incomplete todo, () { });
测试仍然很容易读懂但现在缩进少了一些。这主要取决于个人喜好选择您更喜欢的风格即可。
现在我们可以编写断言了。首先我们将创建我们的起始状态然后将其传递到toggleDone中以及我们要切换的todo的ID。toggleDone将返回我们的最终状态然后我们可以对其进行断言 import { toggleDone } from ../app/state-functions; test(tooggleDone completes an incomplete todo, () { const startState [{ id: 1, done: false, text: Buy Milk }]; const finState toggleDone(startState, 1); expect(finState).toEqual([{ id: 1, done: true, text: Buy Milk }]); });
现在我使用toEqual进行断言。您应该使用toBe来测试原始值例如字符串和数字使用toEqual测试对象和数组。toEqual是专门用于处理数组和对象的并且会递归检查给定对象内的每个字段或项目以确保其匹配。
有了这个我们现在可以运行npm test并看到我们的状态函数测试通过 PASS __tests__/state-functions.test.js ✓ tooggleDone completes an incomplete todo (9ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 passed, 0 total Time: 3.166s
配置热更新
在更改测试文件后手动再次运行npm test有点繁琐。 Jest最好的功能之一是其监视模式它会监视文件更改并相应地运行测试。它甚至可以根据更改的文件确定要运行的子集测试。它非常强大和可靠您可以在监视模式下运行Jest并在整天编写代码时保留它。
要在监视模式下运行它您可以运行npm test -- watch。在第一个--之后传递给npm test的任何内容都将直接传递给基础命令。这意味着这两个命令是等效的
npm test -- --watchjest --watch
我建议您在另一个终端窗口中将Jest保留运行以便在本教程的其余部分中使用。
在继续测试React组件之前我们将在另一个状态函数上编写一个测试。在实际应用程序中我会编写更多的测试但是为了本教程的缘故我将跳过其中一些。现在让我们编写一个测试以确保我们的deleteTodo函数正常工作。在查看下面我的编写方式之前请尝试自己编写它并查看您的测试与我的测试有何不同。
请记住您需要更新顶部的导入语句以导入deleteTodo和toggleTodo
import { toggleDone, deleteTodo } from ../app/state-functions;这是我编写测试用例 test(deleteTodo deletes the todo it is given, () { const startState [{ id: 1, done: false, text: Buy Milk }]; const finState deleteTodo(startState, 1); expect(finState).toEqual([]); });
这个测试与第一个测试并没有太大的区别我们设置起始状态运行我们的函数然后对最终状态进行断言。如果您已在监视模式下运行Jest请注意它如何检测到您的新测试并运行它以及它运行速度的快速性这是一种在写测试时立即得到反馈的好方法。
上面的测试还演示了测试的过程其中包括
设置执行要测试的功能对结果进行断言
通过以这种方式布局测试您会发现更容易跟踪和处理它们。
现在我们已经满意测试我们的状态函数让我们继续测试React组件。
测试 React 组件
值得注意的是默认情况下我实际上鼓励您不要在React组件上编写太多测试。您想要非常彻底测试的任何内容例如业务逻辑都应该从组件中提取出来并作为独立的函数存在就像我们之前测试的状态函数一样。尽管如此有时测试一些React交互例如确保用户单击按钮时调用特定函数并传递正确参数是很有用的。我们将从测试我们的React组件是否呈现正确的数据开始然后再看看如何测试交互。
为了编写测试我们将安装Enzyme这是由Airbnb编写的包装库使测试React组件变得更加容易。
注意自本文首次编写以来React团队已经转向Enzyme并推荐使用[React Testing LibraryRTL](https://testing-library.com/docs/react-testing-library/intro)。阅读该页面很值得一看。如果您正在维护已经使用Enzyme测试的代码库则无需放弃所有内容并转移但对于新项目我建议考虑RTL。
除了Enzyme之外我们还需要安装适用于我们使用的React版本的适配器。对于React v16使用enzyme-adapter-react-16但对于React v17目前没有官方适配器可用因此我们必须使用非官方版本。请注意该软件包旨在作为临时措施直到正式支持发布并将在那时被弃用。
npm install --save-dev enzyme wojtekmaj/enzyme-adapter-react-17我们需要对 Enzyme 进行少量设置。在项目的根目录中创建setup-tests.js以下代码并将其放入其中 import { configure } from enzyme; import Adapter from wojtekmaj/enzyme-adapter-react-17; configure({ adapter: new Adapter() });
然后我们需要告诉Jest在执行任何测试之前为我们运行此文件。我们可以通过配置setupFilesAfterEnv选项来实现这一点。您可以将Jest配置放在自己的文件中但我喜欢使用package.json并将东西放在jest对象中Jest也会自动检测到它 jest: { setupFilesAfterEnv: [ ./setup-tests.js ] }
现在我们准备编写一些测试了让我们测试该Todo组件是否在段落内呈现其待办事项的文本。首先我们将创建__tests__/todo.test.js并导入我们的组件 import Todo from ../app/todo; import React from react; import { mount } from enzyme; test(Todo component renders the text of the todo, () { });
从Enzyme导入了mount。mount函数用于呈现我们的组件然后允许我们检查输出并对其进行断言。即使我们在Node中运行测试我们仍然可以编写需要DOM的测试。这是因为Jest配置了jsdom一个在Node中实现DOM的库。这很好因为我们可以编写基于DOM的测试而无需每次启动浏览器进行测试。
可以使用mount来创建我们的Todo const todo { id: 1, done: false, name: Buy Milk }; const wrapper mount( Todo todo{todo} / );
然后我们可以调用wrapper.find给它一个CSS选择器以查找我们希望包含Todo文本的段落。这个API可能会让您想起jQuery这是有意设计的。这是一个在渲染的输出中搜索匹配元素的非常直观的API。
const p wrapper.find(.toggle-todo);最后我们可以断言其中的文本是Buy Milk
expect(p.text()).toBe(Buy Milk);完整的测试用例是这样的 import Todo from ../app/todo; import React from react; import { mount } from enzyme; test(TodoComponent renders the text inside it, () { const todo { id: 1, done: false, name: Buy Milk }; const wrapper mount( Todo todo{todo} / ); const p wrapper.find(.toggle-todo); expect(p.text()).toBe(Buy Milk); });
现在我们有了一个测试可以检查我们是否成功地渲染了todos。 接下来让我们看一下如何使用Jest的spy功能来断言具有特定参数的函数被调用。在我们的情况下很有用因为我们有一个Todo组件它被赋予了两个函数作为属性当用户单击按钮或执行交互时应该调用这些函数。
在这个测试中我们将断言当Todo被单击时组件将调用它所赋予的doneChange属性 test(Todo calls doneChange when todo is clicked, () { });
我们希望有一个可以用来跟踪其调用及其调用参数的函数。然后我们可以检查当用户单击Todo时doneChange函数是否被调用并且被调用时使用了正确的参数。幸运的是Jest在功能上提供了这个功能来使用spy间谍。spy是一种函数其实现方式并不重要您只需要关心它何时以及如何被调用。可以将其想象为您在侦察该函数。要创建一个spy我们调用jest.fn()
const doneChange jest.fn();
这提供了一个函数我们可以对其进行监视并确保其被正确调用。让我们从使用正确的props来呈现我们的Todo开始 const todo { id: 1, done: false, name: Buy Milk }; const doneChange jest.fn(); const wrapper mount( Todo todo{todo} doneChange{doneChange} / );
接下来我们可以再次查找我们的段落就像在前面的测试中一样
const p wrapper.find(.toggle-todo);
然后我们可以调用simulate它来模拟用户事件并click作为参数传递
p.simulate(click);现在我们只需要断言我们的spy函数是否被正确调用。在这种情况下我们期望它被调用时使用了ID为1的todo。我们可以使用expect(doneChange).toBeCalledWith(1)来断言这一点然后我们的测试就完成了 test(TodoComponent calls doneChange when todo is clicked, () { const todo { id: 1, done: false, name: Buy Milk }; const doneChange jest.fn(); const wrapper mount( Todo todo{todo} doneChange{doneChange} / ); const p wrapper.find(.toggle-todo); p.simulate(click); expect(doneChange).toBeCalledWith(1); });
结论
Facebook很久以前就发布了Jest但最近已经被广泛采用和改进。它已经快速成为JavaScript开发人员的首选而且它只会变得更好。如果你以前尝试过Jest并且不喜欢它我无法足够地鼓励你再次尝试它因为现在它基本上是一个完全不同的框架。它快速重复运行规格非常出色提供了出色的错误消息并且有一个出色的表达式API用于编写良好的测试。 感谢每一个认真阅读我文章的人
作为一位过来人也是希望大家少走一些弯路如果你不想再体验一次学习时找不到资料没人解答问题坚持几天便放弃的感受的话在这里我给大家分享一些自动化测试的学习资源希望能给你前进的路上带来帮助。 软件测试面试文档
我们学习必然是为了找到高薪的工作下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料并且有字节大佬给出了权威的解答刷完这一套面试资料相信大家都能找到满意的工作。 视频文档获取方式 这份文档和视频资料对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴我走过了最艰难的路程希望也能帮助到你以上均可以分享点下方小卡片即可自行 文章转载自: http://www.morning.msbct.cn.gov.cn.msbct.cn http://www.morning.qjzgj.cn.gov.cn.qjzgj.cn http://www.morning.lkbdy.cn.gov.cn.lkbdy.cn http://www.morning.jntdf.cn.gov.cn.jntdf.cn http://www.morning.pqcbx.cn.gov.cn.pqcbx.cn http://www.morning.kldtf.cn.gov.cn.kldtf.cn http://www.morning.wdshp.cn.gov.cn.wdshp.cn http://www.morning.mxmzl.cn.gov.cn.mxmzl.cn http://www.morning.yaqi6.com.gov.cn.yaqi6.com http://www.morning.dxsyp.cn.gov.cn.dxsyp.cn http://www.morning.snxbf.cn.gov.cn.snxbf.cn http://www.morning.rbrd.cn.gov.cn.rbrd.cn http://www.morning.qztsq.cn.gov.cn.qztsq.cn http://www.morning.jfmjq.cn.gov.cn.jfmjq.cn http://www.morning.hbqhz.cn.gov.cn.hbqhz.cn http://www.morning.mxcgf.cn.gov.cn.mxcgf.cn http://www.morning.bjjrtcsl.com.gov.cn.bjjrtcsl.com http://www.morning.pwghp.cn.gov.cn.pwghp.cn http://www.morning.nfcxq.cn.gov.cn.nfcxq.cn http://www.morning.sjjq.cn.gov.cn.sjjq.cn http://www.morning.gqcsd.cn.gov.cn.gqcsd.cn http://www.morning.jhrtq.cn.gov.cn.jhrtq.cn http://www.morning.plcyq.cn.gov.cn.plcyq.cn http://www.morning.fbjnr.cn.gov.cn.fbjnr.cn http://www.morning.ldcrh.cn.gov.cn.ldcrh.cn http://www.morning.wjhpg.cn.gov.cn.wjhpg.cn http://www.morning.dbrnl.cn.gov.cn.dbrnl.cn http://www.morning.dkslm.cn.gov.cn.dkslm.cn http://www.morning.zthln.cn.gov.cn.zthln.cn http://www.morning.bksbx.cn.gov.cn.bksbx.cn http://www.morning.flqbg.cn.gov.cn.flqbg.cn http://www.morning.fqlxg.cn.gov.cn.fqlxg.cn http://www.morning.csznh.cn.gov.cn.csznh.cn http://www.morning.dhckp.cn.gov.cn.dhckp.cn http://www.morning.dyght.cn.gov.cn.dyght.cn http://www.morning.demoux.com.gov.cn.demoux.com http://www.morning.lsyk.cn.gov.cn.lsyk.cn http://www.morning.rmqlf.cn.gov.cn.rmqlf.cn http://www.morning.tjmfz.cn.gov.cn.tjmfz.cn http://www.morning.kxrhj.cn.gov.cn.kxrhj.cn http://www.morning.gyqnp.cn.gov.cn.gyqnp.cn http://www.morning.wfzdh.cn.gov.cn.wfzdh.cn http://www.morning.cdygl.com.gov.cn.cdygl.com http://www.morning.qbmjf.cn.gov.cn.qbmjf.cn http://www.morning.nqwz.cn.gov.cn.nqwz.cn http://www.morning.tdmgs.cn.gov.cn.tdmgs.cn http://www.morning.llyqm.cn.gov.cn.llyqm.cn http://www.morning.kyctc.cn.gov.cn.kyctc.cn http://www.morning.nyplp.cn.gov.cn.nyplp.cn http://www.morning.smj79.cn.gov.cn.smj79.cn http://www.morning.ns3nt8.cn.gov.cn.ns3nt8.cn http://www.morning.pynzj.cn.gov.cn.pynzj.cn http://www.morning.qjbxt.cn.gov.cn.qjbxt.cn http://www.morning.hdrsr.cn.gov.cn.hdrsr.cn http://www.morning.wphfl.cn.gov.cn.wphfl.cn http://www.morning.yqwsd.cn.gov.cn.yqwsd.cn http://www.morning.fyskq.cn.gov.cn.fyskq.cn http://www.morning.pnmnl.cn.gov.cn.pnmnl.cn http://www.morning.xlpdm.cn.gov.cn.xlpdm.cn http://www.morning.ydxx123.cn.gov.cn.ydxx123.cn http://www.morning.dzqyn.cn.gov.cn.dzqyn.cn http://www.morning.ndynz.cn.gov.cn.ndynz.cn http://www.morning.ztqj.cn.gov.cn.ztqj.cn http://www.morning.pbbzn.cn.gov.cn.pbbzn.cn http://www.morning.rtbj.cn.gov.cn.rtbj.cn http://www.morning.jppb.cn.gov.cn.jppb.cn http://www.morning.lmdfj.cn.gov.cn.lmdfj.cn http://www.morning.rlxnc.cn.gov.cn.rlxnc.cn http://www.morning.mknxd.cn.gov.cn.mknxd.cn http://www.morning.ptwrz.cn.gov.cn.ptwrz.cn http://www.morning.pshpx.cn.gov.cn.pshpx.cn http://www.morning.qgjgsds.com.cn.gov.cn.qgjgsds.com.cn http://www.morning.srkqs.cn.gov.cn.srkqs.cn http://www.morning.horihe.com.gov.cn.horihe.com http://www.morning.wcgcm.cn.gov.cn.wcgcm.cn http://www.morning.nqrfd.cn.gov.cn.nqrfd.cn http://www.morning.kdbcx.cn.gov.cn.kdbcx.cn http://www.morning.mrnnb.cn.gov.cn.mrnnb.cn http://www.morning.rnnq.cn.gov.cn.rnnq.cn http://www.morning.zzfjh.cn.gov.cn.zzfjh.cn