ようへいの日々精進XP

よかろうもん

改めて exercism.io の始めたのでメモ

tl;dr

exercism.io

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 の使い方 (問題の取得, 提出方法) を簡単にまとめてみた. 世界中の強者メンターから教えを請いながら少しでもプログラミングのスキルを上げていきたいと思っている.