# grunt-nightwatch-auto

> 这里的auto指的是包括测试用例也能自动生成。前端UI自动化测试，可以监控前端展示是否正常，展示正常，说明样式正常、前端静态资源加载正常以及数据接口正常。本组件实现了全自动化：对正常页面采样，保存样本文件；回归测试时，使用样本文件与当前页面进行比较，发现问题。整个过程只需要，把需要监控/测试的页面url地址添加到配置列表中，执行即可，**不需要写测试用例**。


### 概述
对于一个页面的测试流程如下（多个页面可以认为是这个流程的重复）：
![对于单个页面的样式测试流程](http://cdn.liquidliang.cc/cdn/img/dgymyslct.png)

如果测试不通过，可以根据输出的报告定位具体是什么问题。如果是样式发生了变化，可以把resample目录中相应的样本文件移动到sample目录中覆盖旧的样本文件；如果是动态页面中存在允许的高度和宽度的变化，或者某个组件允许不展示，则可以把notok目录下相应的文件修改成白名单文件，存放在white目录中。
整个过程都不需要写任何一个测试用例，这在实践中确实提高了工作效率、减少了维护和推广成本。
在测试过程中，会收集页面中通过console.error打印的所有信息，以及XHR请求中非200的请求。

### 运行环境
安装nodejs环境[http://nodejs.org](http://nodejs.org "nodejs.org. ")

安装7.x以上的JDK
[http://www.oracle.com/technetwork/java/javase/downloads/index.html](http://www.oracle.com/technetwork/java/javase/downloads/index.html " Java Development Kit (JDK) ")


本插件是基于nightwatchjs进行开发的，因此开始时需要先执行以下命令，安装nightwatch和grunt

```shell
npm install -g nightwatch grunt
```
###使用方式一
本项目也是一个demo，如果你希望在本项目的基础上进行修改，可以整个下载到本地。然后，在目录中执

```shell
npm install
```
安装完了之后，可以执行grunt，看到demo运行的效果（会打开chrome浏览器打开相关页面）。如果报错，建议进行下面的尝试：

1、把chrome浏览器更新到最新版本；

2、下载相应的chromedriver文件，对`./nightwatch/web_driver/`目录中的相关文件进行替换。可以在最新的几个版本中尝试。[https://chromedriver.storage.googleapis.com/index.html](https://chromedriver.storage.googleapis.com/index.html "所有chromedriver版本列表")
这里有个坑：那个列表不是按照从旧到新排列的，需要擦亮眼睛才能找到最新版本！（demo中用到的是2.28）

修改配置的方式可以参考下文对Gruntfile.js文件的介绍。

###使用方式二
当然，你可以通过npm安装grunt-nightwatch-auto。在你的项目目录下执行

```shell
npm install grunt-nightwatch-auto --save-dev
```

下载最新selenium-server-standalone-{VERSION}.jar（demo中用到的是3.3.1）放在项目的目录中（配置“server_path”需填写该文件路径）
[http://selenium-release.storage.googleapis.com/index.html](http://selenium-release.storage.googleapis.com/index.html "selenium下载")

下载相应的chromedriver文件（配置中的"webdriver.chrome.driver"需填写该文件路径）**如果环境配好后运行grunt不能正常打开chrome浏览器或者不能打开页面，则可能chromedriver文件的版本没选对，可以选前一个版本** [https://sites.google.com/a/chromium.org/chromedriver/](https://sites.google.com/a/chromium.org/chromedriver/ "chromedriver")

在你的Gruntfile.js文件中，添加如下代码:

```js
grunt.loadNpmTasks('grunt-nightwatch-auto');
```

在Gruntfile.js文件中同时需要添加一个名为 `nightwatch_auto` 的代码片段在`grunt.initConfig()`中。

```js
grunt.initConfig({
  nightwatch_auto: {
    aim: {
        default: "https://developer.mozilla.org/zh-CN",
        gray: 'https://developer.mozilla.org/en'
    },
    dir: 'nightwatch',
    chromeOptions: {
        "mobileEmulation": {
            "deviceName": "Apple iPhone 6"
        }
    },
    sreenshot_folder: "",
    urls: [
        '/docs/Web/HTML',
        '/docs/Web/HTML/Element/section',
    ],
    "selenium": {
        "start_process": true,
        "server_path": "nightwatch/selenium/selenium-server-standalone-2.53.0.jar",
        "cli_args": {
            "webdriver.chrome.driver": "nightwatch/web_driver/chromedriver.exe"
        }
    },
},
});
```

### Options

#### options.aim
Type: `Object`
Default value: `{}`

key是grunt任务的目标名， value是对应页面的location.origin 部分

#### options.dir
Type: `String`
Default value: `'nightwatch'`

用于存放测试任务过程文件的目录名

./json/sample  存放页面样式采样文件（自动生成）

./json/resample  对测试不通过的页面重采样的文件（自动生成）

./json/notok   存放不通过的样式（自动生成）

./json/white   存放白名单（手工添加）

./reports	   报告文件

./template.ejs 程序入口模板（可修改）

#### options.chromeOptions:
Type: `Object`
Default value: ```{
    "mobileEmulation": {
        "deviceName": "Apple iPhone 6"
    }
}```
chrome浏览器模拟的机器，如果不需要模拟手机，可以配成
```
{
	"mobileEmulation": {}
}
```
#### options.sreenshot_folder
Type: `String`
Default value: `'nightwatch/reports'`
截图文件存放目录


#### options.urls
Type: `Array`
Default value: `[]`
被测试页面的列表，元素是页面对应的相对地址


#### options.selenium
Type: `Object`
Default value: `{}`
具体设置请参考：[http://nightwatchjs.org/getingstarted#selenium-settings](http://nightwatchjs.org/getingstarted#selenium-settings "nightwatch的selenium设置")



### 执行命令
`grunt nightwatch_auto`  如果不存在页面样式的采样文件，执行的是采用操作。如果存在，则执行的是测试操作。如果页面结构发生变化，可以删除其相应的样本文件，执行重新采样。

`grunt nightwatch_auto:gray`  执行对应目标为gray的测试任务


### 白名单
有些页面中的元素的样式可能会存在变化，这些变化又是合理的。此时可以为该元素添加白名单。白名单存放在./json/white目录中，文件名与样本的json文件一致，与测试过程中生成的./json/notok中的文件一致，格式也与./json/notok中相应的文件一致。
格式类似下面所示(对于width、height，支持范围，其他属性支持数组枚举)
```
{
  "body>#_persona_login": {
    "height": 100
  },
  "body>#content": {
    "height": "ignore"
  },
  "body>#nav-access>LI>#skip-main": {
    "ignore": true
   },
  "body>#nav-access>LI>#skip-optional": {
    "optional": true
  },
  "body>#main-footer": {
    "padding": "ignore",
    "margin": "0px",
    "color": ["rgb(33, 122, 192)", "rgb(33, 0, 192)", "rgb(33, 122, 255)"],
    "background": "ignore",
    "width": "37-350",
    "position": "absolute",
    "font": "normal normal bold normal 14px / 21px \"Open Sans\", Arial, sans-serif",
    "height": 45
  }
}
```
key为css选择器，value是一个对象，该对象属性对应css样式（其中，width和height是元素宽高的像素值）
测试中，如果取得元素的样式命中了白名单中设置的css值，认为测试通过，如果白名单中设置的css值"ignore"为true，则跳过对该元素相应css值的判断; 如果设置"optional"为true，则当该元素不存在时，跳过对其子元素的检查。宽度和高度比较特别，目前的策略是大于白名单中的值则认为正常。


## 测试报告
项目中集成了，修改后的grunt-nightwatch-report，只需在grunt.initConfig中添加相应的配置即可。

```js
grunt.initConfig({
    nightwatch_report: {
      files: ['nightwatch/reports/*.xml'], //
      options: {
        outputDir: 'nightwatch/reports/',
        title: '自动化测试demo',
        autoOpen: true,
        message_parser: function (str) {
          var arr = str.split('|');
          var url = arr[0];
          if (/^[:\d\w.#?!-_/]+$/.test(url)) {
            return '<a href="https://developer.mozilla.org/zh-CN' + url + '" target="_blank">' + url + '</a>';
          }
          return str;
        }
      }
  },
});
```
执行： `grunt nightwatch_report`
在demo中也可以使用`npm run demo`跑完整个流程（window中，mac里面我这边是前一句没跑完就跑report了）

## Release History
 * 2016-11-22   v0.1.0   创建项目
 * 2016-11-23   v0.1.2   优化白名单
 * 2016-12-15   v0.2.4   优化测试流程
 * 2016-12-20   v0.2.5   修复测试过程的bug
 * 2017-03-28	  v0.2.7	 集成测试报告
 * 2017-07-11	  v0.3.0	 增强对页面代码质量的监控，收集页面console.error，及XHR中异常的信息。
