rubyで世界のナベアツさんのネタを実装してテストを書く

qiitaにも書いたのですが、どちらのほうがよく見てもらえるか試したくて、全く同じ内容をブログにも書いときます。

rubyで世界のナベアツさんのネタを実装してテストを書く - Qiita

PHPで世界のナベアツさんのネタを実装する - Qiita

qiitaには書かなかった感想

  • 仕事でPHPばかり書いているとrubyのifに()をつけたりして、慣れなくて戸惑う。
  • 少し書いてたらruby書きやすくてとてもいいなとなる。
  • PHPで書いてみたら記述量がやっぱり多いなと感じた。

なぜやろうと思ったか

  • rspec単体テストを書いてみたかった
  • 単純なプログラムがよかった
  • 世界のナベアツさんのネタがシンプルかつ無駄がなく面白いから
  • 思いついたから
  • やりたかったから

仕様

  • 最初に「これから面白いことつまりオモローなことをします」という
  • 1から40まで数を数える
  • 3がつく数字のときアホになる
  • 3の倍数のときアホになる
  • 5の倍数のとき犬になる(3と5の倍数なら犬になる)
  • 最後に「オモロー」という

まず、実装

TSUJO_KAO_MOJI = "( ・`ω・´)" # 通常
AHO_KAO_MOJI = "ʅ( ՞ਊ՞)ʃ≡" # アホのつもり
DOG_KAO_MOJI = "∪・ω・∪" # イッヌのつもり

puts 'これから面白いことつまりオモローなことをします'

(1..40).each do |figure|
  sleep 0.5
  
  if figure % 5 == 0
    puts figure.to_s + DOG_KAO_MOJI
    next
  end

  if figure % 3 == 0
    puts figure.to_s + AHO_KAO_MOJI
    next
  end

  if /3/ =~ figure.to_s
    puts figure.to_s + AHO_KAO_MOJI
    next
  end
  
  puts figure.to_s + TSUJO_KAO_MOJI
end

puts 'オモロー'

ruby omoro.rbで実行

1( ・`ω・´)
2( ・`ω・´)
3ʅ( ՞ਊ՞)ʃ≡
4( ・`ω・´)
5∪・ω・∪
6ʅ( ՞ਊ՞)ʃ≡
7( ・`ω・´)
8( ・`ω・´)
9ʅ( ՞ਊ՞)ʃ≡
10∪・ω・∪
11( ・`ω・´)
12ʅ( ՞ਊ՞)ʃ≡
13ʅ( ՞ਊ՞)ʃ≡
14( ・`ω・´)
15∪・ω・∪
16( ・`ω・´)
17( ・`ω・´)
18ʅ( ՞ਊ՞)ʃ≡
19( ・`ω・´)
20∪・ω・∪
21ʅ( ՞ਊ՞)ʃ≡
22( ・`ω・´)
23ʅ( ՞ਊ՞)ʃ≡
24ʅ( ՞ਊ՞)ʃ≡
25∪・ω・∪
26( ・`ω・´)
27ʅ( ՞ਊ՞)ʃ≡
28( ・`ω・´)
29( ・`ω・´)
30∪・ω・∪
31ʅ( ՞ਊ՞)ʃ≡
32ʅ( ՞ਊ՞)ʃ≡
33ʅ( ՞ਊ՞)ʃ≡
34ʅ( ՞ਊ՞)ʃ≡
35∪・ω・∪
36ʅ( ՞ਊ՞)ʃ≡
37ʅ( ՞ਊ՞)ʃ≡
38ʅ( ՞ਊ՞)ʃ≡
39ʅ( ՞ਊ՞)ʃ≡
40∪・ω・∪
オモロー

できた。 ただこれだとメソッドがなく全部の処理が一緒で単体テストが書けない。 メソッドを責務ごとに分けた。

class Omoro
  TSUKAMI = "これから面白いことつまりオモローなことをします"
  OCHI = "オモロー"
  TSUJO_KAO_MOJI = "( ・`ω・´)"
  AHO_KAO_MOJI = "ʅ( ՞ਊ՞)ʃ≡"
  DOG_KAO_MOJI = "∪・ω・∪"
  
  # ネタ
  def main(max_kazu = 40)
    speak(TSUKAMI)
    
    (1..max_kazu).each do |figure|
      sleep 1
      kao_moji = verification(figure)
      serif = make_serif(figure, kao_moji)
      speak(serif)
    end
    
    speak(OCHI)
  end
  
  # セリフを作る
  def make_serif(figure, kao_moji)
    figure.to_s + kao_moji
  end
  
  # 判断する
  def verification(figure)
    if figure % 5 == 0
      return DOG_KAO_MOJI
    end
    
    if figure % 3 == 0 || /3/ =~ figure.to_s
      return AHO_KAO_MOJI
    end
    TSUJO_KAO_MOJI
  end
  
  # 話す
  def speak(serif)
    puts serif
  end
end
  
omoro = Omoro.new
omoro.main(40)

オモロークラスができました。 余談ですが、mainメソッドに任意の数を渡すことで数えるマックスの数字を動的に変えられます。 400と入れると300-399までアホか犬になります。 人力だと大変ですが、プログラムで書くと簡単です。

テストを書きます。 勉強中です。 letがよくわからないので使っていません。 もし、優しいマサカリをお持ちの方は、コメントでexampleを書いてください。

require 'rspec'
require_relative '../omoro_class'

RSpec.describe Omoro do
    TSUJO_KAO_MOJI = "( ・`ω・´)"
    AHO_KAO_MOJI = "ʅ( ՞ਊ՞)ʃ≡"
    DOG_KAO_MOJI = "∪・ω・∪"

  it '数字(1)+顔文字(( ・`ω・´))のセリフを生成すること' do
    expect(Omoro.new.make_serif(1, TSUJO_KAO_MOJI)).to eq '1( ・`ω・´)'
  end

  it '数字(3)+顔文字(3ʅ( ՞ਊ՞)ʃ≡)のセリフを生成すること' do
    expect(Omoro.new.make_serif(3, AHO_KAO_MOJI)).to eq '3ʅ( ՞ਊ՞)ʃ≡'
  end

  it 'イッヌ' do
    expect(Omoro.new.make_serif(5, DOG_KAO_MOJI)).to eq '5∪・ω・∪'
  end

  it '3がつく' do
    expect(Omoro.new.make_serif(33, 'ʅ( ՞ਊ՞)ʃ≡')).to eq '33ʅ( ՞ਊ՞)ʃ≡'
  end

  it 'verification' do
    omoro = Omoro.new
    (1..40).each do |figure|
      if figure % 5 == 0
        expect(omoro.verification(figure)).to eq DOG_KAO_MOJI
      elsif figure % 3 == 0 || /3/ =~ figure.to_s
        expect(omoro.verification(figure)).to eq AHO_KAO_MOJI
      else
        expect(omoro.verification(figure)).to eq TSUJO_KAO_MOJI
      end
    end
  end

  it 'main' do
    omoro = Omoro.new
    expect { omoro.main(5) }.to output(
      "これから面白いことつまりオモローなことをします\n1( ・`ω・´)\n2( ・`ω・´)\n3ʅ( ՞ਊ՞)ʃ≡\n4( ・`ω・´)\n5∪・ω・∪\nオモロー\n").to_stdout
  end
end

個人的にverificationメソッドとmainメソッドは改良できそうな気がしますが、やり方がわかりませんでした。

参考文献

桂三度 - Wikipedia

[Ruby] Rspecで始めるユニットテスト(単体テスト) | qs Developers

Rspecで標準出力をテストする - Qiita

これを書いたあとPHPでも書きたくなりやってみました。 テストは書いてません。 実行したらrubyでやったものと同じように出力できたのでよしとします。

<?php
class Omoro
{
  const TSUKAMI = "これから面白いことつまりオモローなことをします";
  const OCHI = "オモロー";
  const TSUJO_KAO_MOJI = "( ・`ω・´)";
  const AHO_KAO_MOJI = "ʅ( ՞ਊ՞)ʃ≡";
  const DOG_KAO_MOJI = "∪・ω・∪";

  // ネタ
  public function main($max_kazu = 40)
  {
    $this->speak(self::TSUKAMI);

    for ($figure = 1; $figure <= $max_kazu; $figure++) {
      sleep(1);
      $kao_moji = $this->verification($figure);
      $serif = $this->make_serif($figure, $kao_moji);
      $this->speak($serif);
    }

    $this->speak(self::OCHI);
  }

  // セリフを作る
  public function make_serif($figure, $kao_moji)
  {
    return $figure . $kao_moji;
  }

  // 判断する
  private function verification($figure)
  {
    if ($figure % 5 == 0) {
      return self::DOG_KAO_MOJI;
    }

    if ($figure % 3 == 0 || strpos($figure, '3') !== false) {
      return self::AHO_KAO_MOJI;
    }

    return self::TSUJO_KAO_MOJI;
  }

  // 話す
  private function speak($serif)
  {
    echo $serif . "\n";
  }
}

$omoro = new Omoro();
$omoro->main(40);