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 作持續構建和測試,確保內容中引用的圖片和連接無死鏈。
若是你對本文描述的內容感興趣,歡迎發佈評論來交流。