TL;DR; 本文介绍了 to_yaml
的开发过程当中如何采用 TDD
方法开发功能,以及用到的免费服务 GitHub
/ TravisCI
/ RubyGems
。git
TDD
(测试驱动开发)是敏捷开发中的一项核心实践和技术,也是一种设计方法论。 TDD
的原理是在开发功能代码以前,先编写单元测试用例代码,测试代码肯定须要编写什么产品代码。github
to_yaml
是一款命令行工具,将 JSON
输入转为 YAML
文本输出。json
<!--excerpt-->ruby
先从最近使用的 ElasticSearch
提及。 做为通用的日志收集、分析与展现的工具集,ELK
工具栈已经至关普及。 其中在管理 ElasticSearch
集群时,大部分时间都要使用 HTTP
接口跟 JSON
格式数据打交道。app
ES 输出 JSON
数据内容比较多,即便使用 ?pretty
参数,仍然难看清数据的层次关系。 ?pretty
的一个反作用是输出内容过长,浪费了大量的屏幕纵向空间。框架
使用 YAML
格式可以在很大程度上缓解空间的问题。 基于这个想法,作了一个简单的工具出来,发布在了 RubyGems.org。curl
在实际使用 JSON
时,但愿的是能直接将接口输出内容直接转换为 YAML
格式。 如这样的形式:svg
$ curl -s -XGET http://localhost:9200/_mappings | to_yaml
另外,要把这个工具做为软件包
发布出来,方便别的地方使用。 ruby
程序的第一选择便是 gem
。工具
使用 gem
发布还有一个好处:能够利用 ruby
的开发工具,如 bundle
、rspec
等,来发布质量可控的软件。单元测试
gem
框架目录现阶段最简单的工具是 bundle gem
。
$ bundle gem to_yaml Creating gem 'to_yaml'... Code of conduct enabled in config MIT License enabled in config create to_yaml/Gemfile create to_yaml/.gitignore create to_yaml/lib/to_yaml.rb create to_yaml/lib/to_yaml/version.rb create to_yaml/to_yaml.gemspec create to_yaml/Rakefile create to_yaml/README.md create to_yaml/bin/console create to_yaml/bin/setup create to_yaml/CODE_OF_CONDUCT.md create to_yaml/LICENSE.txt create to_yaml/.travis.yml create to_yaml/.rspec create to_yaml/spec/spec_helper.rb create to_yaml/spec/to_yaml_spec.rb Initializing git repo in /private/tmp/to_yaml
更改 to_yaml.gemspec
中的基本信息,全部标记 TODO
的全酌情修改。
在 github
上建立一个代码库。而后 git add . && git commit -am Init && git push
。
如今咱们已经有了基本的框架。
查看 Rakefile
内容以下
require "bundler/gem_tasks" require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) task :default => :spec
命令行执行 rake spec
或 rake
,能够执行默认的测试用例。
来让咱们为 to_yaml
工具写一个最简单的用例。
打开 spec/to_yaml_spec.rb
文件,在 describe ToYaml
与对应 end
直接增长一个用例
it 'parse json with cli' do json_str = '{"a": [1, 2, 3], "b": {"c": "d"}}' yaml_str = '---\na:\n- 1\n- 2\n- 3\nb:\n c: d\n' cli_output = run_cli('./exe/to_yaml', json_str) expect(cli_output).to eq(yaml_str) end
修改 spec/spec_helper.rb
,加入 helper 方法
require 'open3' def run_cli(exe="./exe/to_yaml", input) cmd = %Q{echo \'#{input}\'| bundle exec #{exe}} output = Open3.popen3(cmd) { |stdin, stdout, stderr, wait_thr| stdout.read } end
注意这里面,咱们构造一个 JSON
字符串 json_str
,和一个 YAML
字符串 yaml_str
。 指望的行为是运行 ./exe/to_yaml
命令处理 json_str
后,输出 cli_output
与 yaml_str
一致。
如今执行这个测试 rake spec
或 rake
,毫无悬念失败了。
不过这是一个好的开头,咱们有了明确的目标:让测试成功。
在 to_yaml.gemspec
中,经过 spec.executables
指定了可执行文件的路径为 ./exe/
目录。
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
to_yaml
命令文件就放在这里。
如今建立 exe/to_yaml
文件,加入内容:
#!/usr/bin/env ruby require 'json' require 'yaml' puts JSON.load(STDIN).to_yaml
再简单不过的一个单行脚本。 按咱们的设想,从 STDIN
读入内容,转化为 YAML
格式。 本着 [YAGNI](https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it)
原则,没作任何额外的容错 - -!
如今执行测试
$ rake spec ToYaml has a version number parse json with cli Finished in 0.77046 seconds (files took 0.09961 seconds to load) 2 examples, 0 failures
太棒了,测试用例所有成功。
目前为止的测试还在靠手工驱动执行。 而在实践中,则须要将持续构建整合进开发流程,全部状态都能够追溯,并能及时反馈构建结果。
在 gem
目录下,咱们能够找到一个 .travis.yml
文件。 travis-ci 是开源世界应用最广泛的持续集成工具。
使用 travis-ci
须要先作设置。 到 https://travis-ci.org,使用 github
账号登陆,并从 github
中添加咱们的 to_yaml
项目。
设置完毕,下次咱们 push 代码到 github
,travis-ci
能够自动开始构建。 为了方便从 GitHub
页面看到项目 Build 状态,在 README.md
文件里增长项目的状态图标
[](https://travis-ci.org/Lax/to_yaml)
刚才已经在本地测试成功,如今将代码 commit 并 push 到 github
。 从 travis-ci
页面,咱们看到已经建立了第一次构建 Build #1。 很幸运,此次构建到结果也成功了!
rake release
能够自动建立一个发布 tag,将代码 push 到 github
。 并 build 出 to_yaml.gem,经过 gem push
发布到 rubygems.org。
下次使用时,直接 gem install to_yaml
,既能够在 PATH
中搜索到 to_yaml
执行程序。
测试一个公开的 JSON
服务:
$ curl -s http://jsonip.com {"ip":"123.45.67.89","about":"/about","Pro!":"http://getjsonip.com"} $ curl -s http://jsonip.com | to_yaml --- ip: 123.45.67.89 about: /about Pro!: http://getjsonip.com
很清爽,有木有!
本文介绍的是一个极简工具的开发过程,但愿你能感觉到测试驱动开发所发挥的做用。
做者在实际项目中也尽量实践 TDD
方法,发布的工具如 aliyun.gem (一个阿里云API的客户端) 也采用了相似流程。 甚至本博客也引入了 travis-ci 作持续构建和测试,确保内容中引用的图片和连接无死链。
若是你对本文描述的内容感兴趣,欢迎发布评论来交流。