【全栈React】第26天: 集成测试

本文转载自:众成翻译
译者:iOSDevLog
链接:http://www.zcfy.cc/article/3808
原文:https://www.fullstackreact.com/30-days-of-react/day-26/

今天我们将编写测试来模拟用户如何与我们的应用进行交互,并在现实的浏览器中测试我们的应用的整个流程。

我们已经到了测试入门的最后部分。我们将用集成测试来结束我们的测试部分。作为对集成测试的一个提醒,它是自动化我们的实际用户在使用我们的应用时体验到的体验的过程。

集成测试

当我们正在进行集成测试时,我们需要让我们的应用实际运行,因为我们需要一个浏览器启动并执行我们的应用。我们将使用一个叫做 selenium的自动化服务器,所以我们需要下载它以及一个非常漂亮的节点自动测试框架,称为Nightwatch

安装

安装 selenium 最简单的方法是通过selenium网站下载http://docs.seleniumhq.org/download/

如果你在使用一个 mac,你可以使用 Homebrewbrew 命令:
brew install selenium-server-standalone

我们还需要安装nightwatch 命令,我们可以使用npm 包管理器来完成。让我们使用--global 标志在全局范围内安装nightwatch:

npm install --global nightwatch

此命令使我们可以在终端的任何位置使用nightwatch命令。我们需要在根目录中添加一个名为nighwatch.json 的配置文件(或nighwatch.conf.js).我们将使用默认的配置文件在nighwatch.json

让我们在根目录中创建文件:

touch nightwatch.json

现在,在新的nightwatch.json 中添加以下内容:

{
  "src_folders" : ["tests"],"output_folder" : "reports","selenium" : {
    "start_process" : false,"server_path" : "","log_path" : "","host" : "127.0.0.1","port" : 4444,"cli_args" : {
      "webdriver.chrome.driver" : "","webdriver.ie.driver" : ""
    }
  },"test_settings" : {
    "default" : {
      "launch_url" : "http://localhost:3000","selenium_port"  : 4444,"selenium_host"  : "localhost","silent": true,"screenshots" : {
        "enabled" : false,"path" : ""
      },"desiredCapabilities": {
        "browserName": "chrome","javascriptEnabled": true,"acceptSslCerts": true
      }
    },"chrome" : {
      "desiredCapabilities": {
        "browserName": "chrome","acceptSslCerts": true
      }
    }
  }
}

Nightwatch给我们提供了很多配置选项,不过我们不会覆盖所有可能的配置方法。出于我们的目的,我们将只使用上面的基本配置,因为它已经足够让集成测试继续进行。

编写测试

我们将在tests/目录中编写我们的Nightwatch测试。让我们先编写一个测试来处理认证工作流。让我们在tests/目录 (与src_folders匹配) 中编写测试,我们将调用tests/auth-flow.js

mkdir tests
touch tests/auth-flow.js

Nightwatch测试可以设置为可导出的对象,其中键是对测试的描述,而该值是一个具有对客户端浏览器的引用的函数。例如,我们将为我们的测试/认证流程设置四测试为tests/auth-flow.js测试。

更新我们的tests/auth-flow.js 文件同以下四测试函数类似:

module.exports = {
  'get to login page': (browser) => {},'logging in': (browser) => {},'logging out': (browser) => {},'close': (browser) => {},}

Each of the functions in our object exports will receive a browser instance which serves as the interface between our test and the selenium webdriver. We have all sorts of available options we can run on this browser variable.我们的对象输出中的每个函数都将接收一个browser 实例,作为我们测试和selenium webdriver之间的接口。我们有各种可用的选项,我们可以运行在这个browser 变量。

让我们编写第一个测试来演示这个函数。我们将设置Nightwatch,以便它启动页面,并单击导航中的登录链接。我们将采取以下步骤执行此操作:

  1. 我们将首先在浏览器中调用url() 功能,要求它在页面上加载一个 url。

  2. 我们将等待页面加载一定的时间。

  3. 我们将找到登录链接并点击它。

我们将在路上设置断言。我们忙起来吧!我们将要求browser 加载我们在配置文件中设置的 URL (对于我们来说,它是http://localhost:3000)

module.exports = {
  'get to login page': (browser) => {
    browser
      // Load the page at the launch URL
      .url(browser.launchUrl)
      // wait for page to load
      .waitForElementVisible('.navbar',1000)
      // click on the login link
      .click('a[href="#/login"]')

    browser.assert.urlContains('login');
  },}

就是这样。在我们走得太远之前,让我们运行这个测试以确保我们的测试设置能够正常工作。我们需要在这里打开3终端窗口。

在第一个终端窗口,让我们启动selenium。如果您下载了 .jar 文件,则可以使用以下命令启动此操作:

java -jar selenium-server-standalone-{VERSION}.jar

如果你通过自制器下载它,你可以使用selenium-server命令:

selenium-server

在第二个窗口中,我们需要启动我们的应用. 记住,我们将要推出的浏览器将 真正地 命中我们的网站,所以我们需要它运行的实例。我们可以用npm start 启动我们的应用:

npm start

最后,在第三个和最后一个终端窗口中,我们将使用nightwatch 命令运行我们的测试。

nightwatch

当我们运行 nightwatch 命令,我们将看到一个 chrome 窗口打开,访问网站,并自动点击登录链接..。(很酷,对吧?)

我们所有的测试都在这一点上通过。让我们实际告诉浏览器在中记录一个用户。

由于第一步将运行,浏览器将已经在登录页上。在测试的第二个密钥中,我们要执行以下步骤:

  1. 我们想 '找到他的用户的电子邮件输入框',并设置一个有效的电子邮件的值。

  2. 我们想点击提交/登录按钮

  3. 我们将等待页面加载 (类似于我们以前所做的)

  4. 我们希望断言页面的文本与我们期望的一样。

  5. 我们将设置一个断言,以确保 URL 是我们所认为的。

在代码中写是直接的。就像我们以前做的那样,让我们用内嵌的注释编写代码:

module.exports = {
  'get to login page': (browser) => {
    browser
      .url(browser.launchUrl)
      .waitForElementVisible('.navbar',1000)
      .click('a[href="#/login"]')

    browser.assert.urlContains('login');
  },'logging in': (browser) => {
    browser
      // set the input email to a valid email
      .setValue('input[type=email]','[[email protected]](https://www.fullstackreact.com/cdn-cgi/l/email-protection)')
      // submit the form
      .click('input[type=submit]')
      // wait for the page to load
      .waitForElementVisible('.navbar',1000)
      // Get the text of the h1 tag
      .getText('.content h1',function(comp) {
        this.assert.equal(comp.value,'Welcome home!')
      })

    browser.assert.urlContains(browser.launchUrl)
  },}

再次运行这些测试 (在第三个终端窗口中):

nightwatch

我们可以用浏览器中的 注销 步骤做类似的事情。要让用户注销,我们将:

  1. 在注销链接上查找并单击

  2. 等待 内容加载到下一页 (其中包含 "你确定吗?"样式按钮)。

  3. 我们将在注销按钮上点击 "我确定"

  4. 我们希望 等待内容再次加载

  5. 我们将 断言他的h1 标记包含我们期望它拥有的值

  6. 我们将确保页面显示 "登录" 按钮

让我们用内嵌的注释实现此操作:

module.exports = {
  'get to login page': (browser) => {
    browser
      .url(browser.launchUrl)
      .waitForElementVisible('.navbar','logging in': (browser) => {
    browser
      .setValue('input[type=email]','[[email protected]](https://www.fullstackreact.com/cdn-cgi/l/email-protection)')
      .click('input[type=submit]')
      .waitForElementVisible('.navbar',1000)
      .getText('.content h1','logging out': (browser) => {
    browser
      // Find and click on the logout link
      .click('a[href="#/logout"]')
      // Wait for the content to load
      .waitForElementVisible('.content button',1000)
      // Click on the button to logout
      .click('button')
      // We'll wait for the next content to load
      .waitForElementVisible('h1',1000)
      // Get the text of the h1 tag
      .getText('h1',function(res) {
        this.assert.equal(res.value,'Welcome home!')
      })
      // Make sure the Login button shows now
      .waitForElementVisible('a[href="#/login"]',1000);
  },}

到目前为止,您可能已经注意到,当测试完成时,chrome 浏览器还没有关闭。这是因为我们没有告诉selenium,我们希望本次课程完成。我们可以使用browser对象上的 end() 命令来关闭连接。这就是为什么我们有最后的和最后一步被称为close

{
  // ...
  'close': (browser) => browser.end()
}

现在,让我们运行整个套件,并确保它再次通过使用nightwatch命令:

nightwatch

就是这样!我们已经做到了,并且已经完全覆盖了3种测试,从低级到假冒一个真正的浏览器实例。现在,我们有了确保我们的应用可以完全部署的工具。

但是等一下,我们还没有发现部署,是吗?敬请关注明天的当我们开始将应用部署到云中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom