tl;dr
exercism.io は出題されたお題のコード書いてサブミットすると世界中のメンターが寄ってたかってレビューしてくれる Web サイト. 以前にお試しでアカウントを作っておいたんだけど, しばらく時間が経って久しぶりにログインしてみたら, バージョンアップしてコマンドラインツールの使い方とか変わってしまっていたので, 使い方をざっくりとメモっておく.
コマンドラインツール
exercism.io はコマンドラインツールが提供されており, そのコマンドラインツールを利用してお題をローカルに取得して, コードを書き, ユニットテストで確認を行い, コマンドラインツールを利用してサブミット (解答の提出) するという流れ. ということで, 以下は, コマンドラインツールを取得して, お題を取得出来るようになるまで.
環境は, Ubuntu 16.04 を利用する. また, 既に exercism.io にログインした状態で, 何らかの言語のトラックにジョインしていることを前提としている.
$ cat /etc/lsb-release DISTRIB_ID=Ubuntu DISTRIB_RELEASE=16.04 DISTRIB_CODENAME=xenial DISTRIB_DESCRIPTION="Ubuntu 16.04.4 LTS"
コマンドラインツールを取得. 最新版のコマンドラインツールはこちらで確認する.
mkdir ~/bin/
wget https://github.com/exercism/cli/releases/download/v3.0.6/exercism-linux-64bit.tgz
tar zxvf exercism-linux-64bit.tgz
展開したら, カレントディレクトリに exercism コマンドが展開されている.
$ exercism version exercism version 3.0.6
トークンを利用して初期設定を行う. トークンは exercism.io にログインした状態で settings
メニューページから取得することが出来る. 以下のように configure
サブコマンドのオプション引数にトークンを指定してコマンドを実行する.
$ exercism configure --token=xxxxxxxxx-xxxx-xxxx-xxx-xxxxxxxxxxxxxx
実行すると, 以下のように出力される.
You have configured the Exercism command-line client: Config dir: /home/${USER}/.config/exercism Token: (-t, --token) xxxxxxxxx-xxxx-xxxx-xxx-xxxxxxxxxxxxxx Workspace: (-w, --workspace) /home/${USER}/exercism API Base URL: (-a, --api) https://api.exercism.io/v1
あとは, download
サブコマンドを利用してお題をダウンロードする. 例えば, Ruby トラックのお題である Hello World をダウンロードした場合は以下のような出力になる.
$ exercism download --exercise=hello-world --track=ruby Downloaded to /home/${USER}/exercism/ruby/hello-world $ ls ~/exercism/ruby/hello-world/ GETTING_STARTED.md README.md hello_world_test.rb
hello_world_test.rb
は以下のような内容になっており, minitest を利用してテストを走らせられるようになっている.
... 略 ... class HelloWorldTest < Minitest::Test def test_say_hi # skip assert_equal "Hello, World!", HelloWorld.hello end end ... 略 ...
未実装の状態でテストを走らせると以下のようにエラーとなる.
$ ruby hello_world_test.rb Error: hello_world_test.rb:4:in `require_relative' cannot load such file -- /home/${USER}/exercism/ruby/hello-world/hello_world ***************************************************** You got an error, which is exactly as it should be. This is the first step in the Test-Driven Development (TDD) process. The most important part of the error is cannot load such file It's looking for a file named hello_world.rb that doesn't exist yet. To fix the error, create an empty file named hello_world.rb in the same directory as the hello_world_test.rb file. Then run the test again. For more guidance as you work on this exercise, see GETTING_STARTED.md. *****************************************************
ということで, これで世界と戦う準備が出来た. テストが通るにコードを書いて, 以下のように submit
サブコマンドで exercism.io にプッシュするとメンター達によるレビューが行われる.
Hello World
せっかくなので
せっかくなので, Ruby と Go で Hello World を解いてみる.
Ruby
Ruby のバージョンは以下の通り.
$ ruby --version ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
まずはお題のダウンロード.
$ exercism download --exercise=hello-world --track=ruby Downloaded to /home/${USER}/exercism/ruby/hello-world
とりあえず, テスト.
$ ruby hello_world_test.rb Error: hello_world_test.rb:4:in `require_relative' cannot load such file -- /home/${USER}/exercism/ruby/hello-world/hello_world
そうですな. hello_world.rb がないっすな.
$ ruby hello_world_test.rb Run options: --seed 30127 # Running: E Finished in 0.000665s, 1504.2003 runs/s, 0.0000 assertions/s. 1) Error: HelloWorldTest#test_say_hi: NameError: uninitialized constant HelloWorldTest::HelloWorld Did you mean? HelloWorldTest hello_world_test.rb:18:in `test_say_hi' 1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
ですです, HelloWorld クラスが実装されてないっすな. 以下のように HelloWorld クラスを実装してみた.
class HelloWorld end
もう一度テスト.
$ ruby hello_world_test.rb Run options: --seed 37451 # Running: E Finished in 0.000980s, 1020.1990 runs/s, 0.0000 assertions/s. 1) Error: HelloWorldTest#test_say_hi: NoMethodError: undefined method `hello' for HelloWorld:Class hello_world_test.rb:18:in `test_say_hi' 1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
ちょっとだけ変わった. hello メソッドが実装されていないですな. 以下のように HelloWorld.hello を実装してみる.
class HelloWorld class << self def hello 'Hello, World!' end end end
これでどうだ.
$ ruby hello_world_test.rb Run options: --seed 36305 # Running: . Finished in 0.000644s, 1553.4201 runs/s, 1553.4201 assertions/s. 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
LGTM.
そして, この解答を submit
サブコマンドを利用して提出すると, 以下のように出力される.
$ exercism submit ~/exercism/ruby/hello-world/hello_world.rb
Your solution has been submitted successfully.
You can complete the exercise and unlock the next core exercise at:
https://exercism.io/my/solutions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ちなみに, 他のソリューションについても考えてみる. 例えば, 以下のようにモジュールに定義したメソッドを extend してみる.
module HelloWorldModule def hello 'Hello, World!' end end class HelloWorld extend HelloWorldModule end
テストを走らせてみると...
$ ruby hello_world_test.rb Run options: --seed 8451 # Running: . Finished in 0.001956s, 511.2582 runs/s, 511.2582 assertions/s. 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
一応, LGTM. こちらのソリューションも submit
しておく.
Go
Go のバージョンは以下の通り.
$ go version go version go1.6.2 linux/amd64
こちらもお題の取得.
$ exercism download --exercise=hello-world --track=go Downloaded to /home/${USER}/exercism/go/hello-world
取得されたファイルは以下の通り.
$ ls ~/exercism/go/hello-world/
README.md hello_test.go hello_world.go
とりあえず, テスト.
$ cd ~/exercism/go/hello-world/ $ go test --- FAIL: TestHelloWorld (0.00s) hello_test.go:13: HelloWorld() = , want Hello, World! FAIL exit status 1 FAIL _/home/kappa/exercism/go/hello-world 0.003s
Hello, World!
が返ってきていないようなので, 上記のように FAIL するので hello_world.go を以下のように実装する.
... 略 .. func HelloWorld() string { return "Hello, World!" }
もう一度, テストを走らせる.
$ go test
PASS
ok _/home/kappa/exercism/go/hello-world 0.002s
LGTM.
こんなに簡単でいいんだろうかと思いつつも submit
する.
$ exercism submit ~/exercism/go/hello-world/hello_world.go
Your solution has been submitted successfully.
You can complete the exercise and unlock the next core exercise at:
https://exercism.io/my/solutions/yyyyyyyyyyyyyyyyyyyyyyyyyy
よし, 次の問題を解くぞー...
ということで
exercism.io の使い方 (問題の取得, 提出方法) を簡単にまとめてみた. 世界中の強者メンターから教えを請いながら少しでもプログラミングのスキルを上げていきたいと思っている.