前端持续集成解决方案

前段时间读到一篇优秀的文章《前端开源项目持续集成三剑客》,就想试着运用到本身的项目中去。(好吧,老实说,我只是个徽章收集爱好者。)html

持续集成

持续集成,这个概念对后端来讲应该并不陌生,甚至能够说是司空见惯吧。可是,这对曾经(除了那些大厂)单元测试都不必定要写的前端来讲,或许是个陌生的词。前端

然而,随着前端飞速地发展,不断吸收后端长久以来积累的经验,以及前端对单元测试愈来愈重视,持续集成做为前端工程化中的一项也渐渐进入人们的视野。node

那么,持续集成到底是什么?react

持续集成(英语:Continuous integration,缩写为 CI),一种软件工程流程,将全部工程师对于软件的工做复本,天天集成数次到共用主线(mainline)上。 —— wikipedialinux

简单来讲,就是以必定的频率将代码整合到一块儿。git

使用持续集成能使项目:github

  • 保持可测试和可发布的状态web

  • 易于追踪错误,当集成产生错误时,能将错误产生的缩小范围到上次成功集成以后的提交chrome

  • 版本回滚也变得垂手可得npm

Travis-CI vs CircleCI

《前端开源项目持续集成三剑客》中,做者推荐了 2 个集成工具,分别是:travis-cicircleci

额...该选哪一个哪?

分别粗略地了解了这两个产品,它俩的网站的都很是简洁,文档也很清晰,功能上也大体相同。虽然,circleci 比 travis-ci 多了 Bitbucket 源码库的支持,可是,有一大硬伤 circleci 只对一个 container 免费,并且,若使用 OS X 须要额外收费。与之相反,travis-ci 只要是 Github 上的开源项目所有免费,且支持在 OS X 运行。

Travis-ci。

注册 travis 只需一步,点击 Sign In 按钮绑定 Github。登陆后,执行 travis 只需如下 3 步:

  1. 添加须要 travis 管理的项目

  2. 为项目添加 .travis.yml 配置文件

  3. 提交代码

与此同时,travis 的配置也极其简单。若是没有什么特别的需求,那么,只需配置运行语言类型及其版本就行。

// .travis.yml
language: node_js
node_js:
  - "6"

这样,一个简单、可用的 travis 配置就完成了。

Travis 构建过程主要分为两步:

  • install:安装依赖,在 node 环境下,默认运行 npm install

  • stript:运行构建命令,在 node 环境下,默认运行 npm test

那么,上面的代码就等价于:

language: node_js
node_js:
  - "6"
install: npm install
script: npm test

固然,travis 不止这两个生命周期,额外的配置需求均可以到官网查看

OK。提交代码试试吧。

travis 的运行信息均可以在 Job log 中看到。

若是运行成功,你就能够经过 https://img.shields.io/travis... https://img.shields.io/travis... 来给你的项目添加 badge 了,就像这样

Tips:其中的 USER, REPO, BRANCH 都要替换成我的信息。

Codecov vs Coveralls

有了构建的徽章,接着再弄一个测试覆盖率的徽章。三剑客文章中用的是 coveralls,但进入它的官网发现,它和当今网站那种简洁风格不一样,画风有点 classic 啊~文档也不太详细,比较简单,就查了下有没有其余更好的?

因而,发现了 codecov

干净、免费,我喜欢。

文档也相对于 coveralls 更清晰、详细。在尝试以后,更是以为个人选择是明智的。^_^

codecov 的使用至关简单,甚至不用看文档就能够轻易配置。

首先,登陆首页,根据本身源码的存储位置选择相应的登陆按钮,这里我选择 Github,第一次登陆会须要你的受权。

受权成功以后,就能看到相似下面的图,分别对应你的我的帐户以及你所加入的组织。

第一次使用时,默认是没有 repository 的,须要经过点击 + Add my first repository 来添加须要 codecov 管理的 repository。

选择相应的 repository 以后,你能够看到一个相似下面的页面。固然,数据什么确定是没有的。

前几个 tab 是用来展现信息的,在配置完成并运行以前是没有信息的,配置的时候只须要看最后一个 setting tab。

切换左侧的菜单,就能分别看到 setting 和 badge 的信息,是否是超级赞?

不管 codecov 仍是 coveralls,它自身都不会去运行测试用例来得到项目代码的覆盖率,而是经过收集覆盖率报告及其余关键信息来静态分析。

codecov 能够接收 lcov, gcov 以及正确的 json 数据格式做为输入信息。

因而,若是你使用 JEST 做为测试框架,并开启测试覆盖率(collectCoverage),因为,JEST 使用 istanbul 生成覆盖率报告,即 lcov。那么,上传报告就异常简单了。只需安装 codecov

npm install codecov --save-dev

而后,在 CI 执行以后,上传报告就行。好比,像这样

language: node_js
node_js:
  - "6"
cache:
  directories: node_modules
script:
  - npm run test:coverage
  # 这里我没有全局安装 codecov,因此要经过 npm 来运行 codecov
  - npm run codecov
os:
  - linux
  - osx

此次的 badge 如何获取上面有写到,这里就再也不展现了。

SAUCELABS vs BrowserStack

跨浏览器测试一样有 2 个选择,此次我同三剑客的做者站在了同一战线,选择使用 SAUCELABS

SAUCELABS 开源免费帐号注册方式隐藏得比较好,找不到的能够点这里

不过,因为 JEST 不支持 end-to-end 测试,因此,为了作跨浏览器测试咱们不得不寻求其余的测试框架来帮助完成这一工做。这里我并不打算使用 karma,即便是 karma 同 SAUCELABS 有现成的集成插件 karma-sauce-launcher 可使用。

不要问我为何,就是这么任(jue)性(jiang)。

你真不问么?那我就说了吧。由于现有的测试框架 JEST 已经能够完成 karma 的大部分工做,单纯为 end-to-end 测试单独引入 karma 就没有必要了。

通过一番资料收集和比较以后,我选择 Nightwatch 来解决跨浏览器测试的问题。

What's Nightwatch?

Nightwatch.js is an automated testing framework for web applications and websites, written in Node.js and using the W3C WebDriver API (formerly Selenium WebDriver).

It is a complete browser (End-to-End) testing solution which aims to simplify the process of setting up Continuous Integration and writing automated tests.

能够从官网的介绍中看到,Nightwatch 对咱们当前想解决的问题简直是正中下怀啊!(若是你的项目使用的是 Angular,那么,你也能够试试 Protractor)

在查资料时,发现 nightwatch 的第一个 issue 居然是尤大大提的。

走得越远,越是发现一路都是大大们留下的足迹。

膜拜大大。

回到正题,使用 nightwatch 创建 e2e 测试也是至关容易的,这里就简要说一下流程。

首先,使用 npm 进行安装,这就很少说了。
而后,在根目录下添加配置文件,能够是 nightwatch.conf.js,也能够是 nightwatch.json。
接着,写对应的测试,API 参考官网
最后,跑测试命令就行了。

主要是来看看,怎么将 nightwatch 的测试同 saucelabs 以及 travis-ci 整合到一块儿。先看看测试文件。

// nightwatch.conf.js
module.exports = {
    src_folders: ['tests/e2e'], // 测试文件目录
    output_folder: 'tests/reports', // 测试报告地址
    custom_commands_path: 'tests/saucelabs', // 自定义命令,这里用来更新测试信息到 saucelabs
    custom_assertions_path: '',
    page_objects_path: '',
    globals_path: '',

    test_workers: {
        enabled: true,
        workers: 'auto'
    },

    test_settings: {
        default: {
            launch_url: 'http://localhost:8080', // 目标地址,用于测试中读取
            selenium_port: 4445, // selenium server 的端口(selenium server 由 saucelabs 提供)
            selenium_host: 'localhost', // selenium server 的地址(selenium server 由 saucelabs 提供)
            username: process.env.SAUCE_USERNAME,
            access_key: process.env.SAUCE_ACCESS_KEY,
            silent: true,
            screenshots: {
                enabled: false,
                path: ''
            },
            globals: {
                waitForConditionTimeout: 15000
            },
            // 如下重要!!!
            desiredCapabilities: {
                build: `build-${process.env.TRAVIS_JOB_NUMBER}`,
                public: 'public',
                'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER
            }
        },

        // 如下是不一样环境的配置
        chrome: {
            desiredCapabilities: {
                browserName: 'chrome'
            }
        },

        firefox: {
            desiredCapabilities: {
                browserName: 'firefox'
            }
        },

        internet_explorer_10: {
            desiredCapabilities: {
                browserName: 'internet explorer',
                version: '10'
            }
        },

        internet_explorer_11: {
            desiredCapabilities: {
                browserName: 'internet explorer',
                version: '11'
            }
        },

        edge: {
            desiredCapabilities: {
                browserName: 'MicrosoftEdge'
            }
        }
    }
};

这里要注意如下几点:(重要!!!这些折磨了我近一周)

  • 运行 localhost 测试,要开启 sauce connect

  • 开启 sauce connect 以后,设置运行环境 selenium_port: 4445, selenium_host: 'localhost'

以上几点是本地测试时需注意的,下面是连通 travis 时需注意的:

  • 配置 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,其中 process.env.TRAVIS_JOB_NUMBER 是 travis 运行时的全局变量

  • 配置 process.env.SAUCE_USERNAMEprocess.env.SAUCE_ACCESS_KEY,后面细讲

  • 配置 buildpublic 属性,分别用于标识测试和查看权限,这两点对最后生成 browser matrix badge 有用,这两点在三剑客的文章中也有提到

配置好了 nightwatch 同 saucelabs,再修改下 travis 的配置,将 saucelabs 整合进去。

// .travis.yml
language: node_js
node_js:
- '6'
cache:
  directories: node_modules
# 用于打包,并在 travis 上启动本地服务,用于 e2e test
before_script:
- npm run build
- node server.js &
script:
- npm run test:coverage
- npm run codecov
- npm run test:e2e
os:
- linux
- osx
env:
  global:
  - secure: v6CRj4CKMqxEQ9MSYKAkbmrBgIBZvoppICx6JyjQXhexPOVQKBvboCgdL0lOOZdGZ9rEqSMXvud97kBAFYd1sdP/kSwXdUct5BOMIT3a5GLtY5aQfOocBwR6IvmZpO2U+4VhrCwkzdaq2Ehq0fAXF1pkxDj9YkJZmwDNhTdfDGkib+AwDyr4TLQFC1QrD/4vmrULb3NZdW1KadFYjLzVF8FMa2tDSYMFFVymYu5nuCa/Z0dqSfFy8McYwBMzThDkDRHMT/sf4zKDPyxUwN7xGfC6T88xzCEaltN6K7MGMGKvl7Y0p7VjYW/+rO38936kj6xuPU6J7Vh2yKPJhhT2LtM7ucuo0XSpIxCxaKXWeEmYl2KkCMWNHgrWACE//WBFRNx/JQHimw+abr1Zt/3V9QmSEvnB3hHB0NQgJ2nVrVDjk51RSVaiP4sfQ8GVqEwr1+wJqe4wz7fV+jvRB9uUGgGsjsBbZi6ZycoMtOBoJ+miviRCjZvf9sOZKfIDjcuE5vETQcE37d/++yplCG0N83Kx+q67mbWXirfNj2CfXp7pwHTN+n21v1BSicXqQ6+jaNzD/pcN/GTHgZ5A+VkdcjSmEziuQTO035i1nnCB9TQdFeRdGdfo6DAiq8YOfyVkQ1lml6lWqbPqa4QWokRUD2yA/hAIzNWe5BeLF2JFQBc=
  - secure: S0vWVM74eiAHhk+kqqvym9aIgqaaGyGz9H3rfmEZoG4iuvXjXRaHOOSHxIRVsh5RYXr0PWHAj24fpN5AyUOlu5NQiwACBqmpw9KZBgVekWFshA5uYmpNpCG9w5/UAQa9q2+EcndOCM4lAyuT2wVJ5WfsHRzIA5jUpK1YmUYtuVICTSkumRoEaxfPkwzcGLF7f6aP7mG1YRKeO1F9+RhBfaGN1kYordxIk/fniH8OFB0XiLZ5OIovaAIYFKic0P1wUFwa78jU2fovdObS8JySl2LP19eaLX0MgAFoPB7oLFPxFBN7FCID41TEodDdZtcNnKJT4uQ/iWRqww2BOwVQM9whyBTg8J4kJZALicR4CzGCuUbdyQd2kh/hNZ9d9SKb6YXdcZElFmh3FY6zgfgv5PAx+jDlkfzmgBh7OD5OM4GVrsCsjnaAlmTUNtRPx9B4ps0gbr25F1PxuNy+MXfwSYJdliL+N01BTpiGyts/EXAraWvEm5YkhWfTnbgc8osd3cX9vwB0QHksK+BpkaEs6XCwU6kGMxAJIlafRv6RslREdTPBpYaXB4sGqdYXWY+YFqNxsAwTB3KWIq/uhZmSkou1jZfZa2QonMuVot68U11U7afmPzX8KOVeO2IEcUjt6I4eCYQ+31xO/wSLIQ1uoRySQ2S9VCzr+yzDpu0KVps=
addons:
  sauce_connect: true

你确定会诧异 global 下面的那两串长