|
背景最近开始做覆盖率的落地,刚完成 android jacoco 的,结果就遇上了项目架构调整,开始往 react native 方向走。而且按照新架构,主要逻辑代码都是在 react native 上编写,所以探究一下怎么获取 react native 的 js 代码覆盖率。
搭建开发环境不得不说,react native 的开发环境搭建文档写得非常好,国内也有一个 React Native 中文网 ,把这部分文档完全翻译过来,并且接地气地写上了国内的一些镜像地址。
搭建开发环境
具体大家可以直接看上面链接里的流程,这里就不再详述了。最终完成了 iOS 和 android 开发环境的搭建,并用 react-native run-ios 和 react-native run-android 两个命令验证成功。
下载并初始化示例项目默认的 AwesomeProject 基本没有逻辑,做覆盖率尝试不是很够。找了下,找到了 facebook 的 2016年 f8 app 。直接使用它就好了。
下载及初始化方法(简要版,详细的建议参照 github 上的文档):
- git clone https://github.com/fbsamples/f8app.git
- cd f8app && npm install
- # ios dependencies
- cd ios; pod install; cd ..
- # Import sample data(官方的说明,实际上运行百分百失败。详细原因请看末尾的踩坑记录。这里后续命令使用能成功运行的命令)
- # npm run import-data # 这条命令运行会报错,请使用下面的命令
- # download db
- wget https://raw.githubusercontent.com/ReactWindows/f8app/data/mongodb/db.zip
- # unzip db
- unzip db.zip -d f8_db
- # run mongodb base on db backup above
- mongod --storageEngine wiredTiger --dbpath f8_db/db
- # Make sure mongodb is running. If it's running, one line starts with "mongodb" should exist
- lsof -iTCP:27017 -sTCP:LISTEN
- # If it's running, it should looks like below:
- # COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
- # mongod 99400 hengjiechen 8u IPv4 0x5fba934ae787aa99 0t0 TCP *:27017 (LISTEN)
- # Start Parse/GraphQL servers
- npm start
复制代码 通过查看 http://localhost:8080/dashboard 和 http://localhost:8080/graphql 确保服务开启成功,并且数据库有相应数据。
(主要看后面蓝色底色的那张图,确认有数据)
- # Android
- react-native run-android
- adb reverse tcp:8081 tcp:8081 # required to ensure the Android app can
- adb reverse tcp:8080 tcp:8080 # access the Packager and GraphQL server
- # iOS
- react-native run-ios<code></code>
复制代码 运行效果:
收集单测覆盖率根据 Unit Testing 可以看到,收集覆盖率的组件为 istanbul ,查了下,基本 js 覆盖率收集用的都是这个工具。
另外,由于 f8 项目是官方写得,Facebook 不使用上面 Unit Testing 里面使用的 Mocha 框架,而是用 Facebook 自己的 jest。经过查阅,jest 本身带有覆盖率相关的配置项,集成了使用 istanbul 收集覆盖率的功能,而且 f8 里面也有一些 jest 的测试用例,直接拿来尝鲜下。
单测相关文件在 ./js/reducers/__tests__ 文件夹里面有一些,通过 npm test 命令即可自动执行,结果类似下面:
- $ npm test
- > F8v2@0.0.1 test /Users/hengjiechen/Develop/ReactNative/f8app
- > jest
- Using Jest CLI v13.0.0, jasmine2, babel-jest
- PASS js/reducers/__tests__/maps-test.js (0.358s)
- PASS js/reducers/__tests__/schedule-test.js (0.376s)
- PASS js/reducers/__tests__/notifications-test.js (0.381s)
- PASS js/tabs/schedule/__tests__/formatDuration-test.js (0.108s)
- PASS js/tabs/schedule/__tests__/formatTime-test.js (0.099s)
- 12 tests passed (12 total in 5 test suites, run time 4.813s)
复制代码 然后根据官方的 配置文档,加入覆盖率相关配置。需要修改 ./package.json 文件,具体修改如下:
- diff --git a/package.json b/package.json
- index 17d9914..27d060e 100644
- --- a/package.json
- +++ b/package.json
- @@ -56,7 +56,9 @@
- "providesModuleNodeModules": [
- "react-native"
- ]
- - }
- + },
- + "collectCoverage": true,
- + "coverageDirectory": "coverage"
- },
- "engines": {
- "node": ">=5.0",
复制代码 PS:也可以把上面的代码块内容保存到 coverage.patch 文件,存到 f8app 根目录,然后 git apply coverage.patch 直接应用变更。
加入覆盖率配置后,同样 npm test ,输出如下:
- $ npm test
- > F8v2@0.0.1 test /Users/hengjiechen/Develop/ReactNative/f8app
- > jest
- Using Jest CLI v13.0.0, jasmine2, babel-jest
- PASS js/reducers/__tests__/schedule-test.js (0.166s)
- PASS js/reducers/__tests__/maps-test.js (0.166s)
- PASS js/reducers/__tests__/notifications-test.js (0.21s)
- PASS js/tabs/schedule/__tests__/formatTime-test.js (0.079s)
- PASS js/tabs/schedule/__tests__/formatDuration-test.js (0.087s)
- 12 tests passed (12 total in 5 test suites, run time 3.347s)
- ------------------------|----------|----------|----------|----------|----------------|
- File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |
- ------------------------|----------|----------|----------|----------|----------------|
- reducers/ | 70.37 | 71.43 | 73.33 | 81.82 | |
- createParseReducer.js | 100 | 100 | 100 | 100 | |
- maps.js | 100 | 100 | 100 | 100 | |
- notifications.js | 59.09 | 56 | 62.5 | 65.52 |... 107,108,110 |
- schedule.js | 77.78 | 78.57 | 75 | 100 | |
- tabs/schedule/ | 100 | 85.71 | 100 | 100 | |
- formatDuration.js | 100 | 100 | 100 | 100 | |
- formatTime.js | 100 | 66.67 | 100 | 100 | |
- ------------------------|----------|----------|----------|----------|----------------|
- All files | 78.38 | 74.6 | 77.78 | 88.24 | |
- ------------------------|----------|----------|----------|----------|----------------|
复制代码 html 的覆盖率报告放在 ./coverage/lcov-report/index.html 中。同时也有 json 格式、xml 格式的覆盖率数据。
小结这次探索基本了解了 rn 项目的大概结构,以及单测中 js 覆盖率怎么获取。基本确定了采用类似 middleware 嵌入到应用中的方式应该可以用来做手工覆盖率收集。具体操作方案后续再继续探索。
意外惊喜在了解 istanbul 的时候,找到了一个好玩的项目:istanbul-middleware 。在项目根目录执行一些命令,即可得到可以实时显示覆盖率的小 Demo 。
使用方法如下命令:
- git clone https://github.com/gotwarlost/istanbul-middleware.git<code></code>
复制代码 # 启动带有实时覆盖率报告的网站- cd istanbul-middleware/test/app
- npm install && node index.js --coverage<code></code>
复制代码 打开 http://localhost:8888 可以访问这个小网站,打开 http://localhost:8888/coverage/ 可以访问实时更新的覆盖率报告(实时更新是指操作后 F5 更新覆盖率报告即可得到最新的覆盖率情况,也可以自己二次开发加个轮询实现真正的实时显示)
大家可以探索下,看通过哪些用例可以让行覆盖率和分支覆盖率达到100% : ) 。后面甚至可以在这个 Demo 基础上进行小网站的功能扩展,甚至拿个单页应用来替代这个网站,开展一下覆盖率小竞赛,让大家更有乐趣地去了解和应用代码覆盖率这个工具。
踩坑记录运行 npm run import-data 提示错误错误信息:
- > F8v2@0.0.1 import-data /Users/hengjiechen/Develop/ReactNative/f8app
- > babel-node ./scripts/import-data-from-parse.js
- Loading Speakers
- SyntaxError: Unexpected token P in JSON at position 0
- at Object.parse (native)
- at /Users/hengjiechen/Develop/ReactNative/f8app/node_modules/node-fetch/lib/body.js:43:15
- at process._tickDomainCallback (internal/process/next_tick.js:129:7)
复制代码 原因: 导入数据依赖的一个远程服务器 Parse.com 。这个服务器已经关站了,导致导入数据时服务端会返回 Parse.com has shutdown - https://parseplatform.github.io/,json 解析器解析出错。
解决方法:改用 github 上其它同学备份的 mongodb 数据库。
- # download db
- wget https://raw.githubusercontent.com/ReactWindows/f8app/data/mongodb/db.zip
- # unzip db
- unzip db.zip -d f8_db
- # run mongodb base on db backup above
- mongod --dbpath f8_db
复制代码 参考资料:https://github.com/fbsamples/f8app/issues/149, https://github.com/fbsamples/f8app/issues/156
|
|