発生する問題
拙著「プロを目指す人のためのRuby入門 改訂2版(通称 チェリー本)」の13.10節の内容に従ってコードを書いていくと、"No type error detected.🫖"と表示されるはずの部分で、エラー(warning)が出力される場合があります。
書籍の記述
$ steep check
# Type checking files:
...........................................................
No type error detected.🫖
発生するエラー
$ steep check
# Type checking files:
................................................................................F..
test/fizz_buzz_test.rb:4:21: [warning] Cannot find the declaration of constant: `Minitest`
│ Diagnostic ID: Ruby::UnknownConstant
│
└ class FizzBuzzTest < Minitest::Test
~~~~~~~~
Detected 1 problem from 1 file
エラーが発生する原因
Steepのバージョンが0.51.0以上だとこの問題が発生します。
どうやらこの仕様変更が影響しているようです。
書籍の執筆時は0.44.1が最新バージョンだったため、この問題は発生しませんでした。
@soutaro さんいわく、
0.51よりも前のバージョンだと、知らない定数がいたら黙って
untyped
にしていた(ように見えた)のが、きちんと「知らない定数があるよ」と報告するためのエラーを導入した
とのことです(ruby-jpのやりとりより)。
参考:バージョンの確認方法
Steepのバージョンは以下のコマンドで確認できます。
$ steep --version
1.6.0
解決方法
まず、rbsのバージョンが2.6.0以上であることを確認してください。
# 2.6.0以上ならOK
$ rbs --version
rbs 3.3.2
2.6.0より古い場合は以下のコマンドで最新のrbsをインストールしてください。
gem install rbs
本書の13.10.2項で
本書の執筆時点ではMinitestの型情報が提供されていないため、以下のようにfizz_buzz.rbsにassert_equalメソッドの型情報を追加してこのエラーを回避することにします。
と書きましたが、rbs 2.6.0からはMinitest用の型情報がデフォルトで提供されるようになりました(参考)。このため、sig/fizz_buzz.rbs
に assert_equal
メソッドの型定義を追加する代わりに以下の修正を行ってください。
書籍に書かれているコード
以下の変更ではSteep 0.51.0以上でエラーが出ます。
# 省略
class FizzBuzzTest
def test_fizz_buzz: -> untyped
+ def assert_equal: (untyped, untyped) -> void
end
Steep 0.51.0以上に対応させる場合のコード
Steep 0.51.0以上では以下のように変更してください。
# 省略
-class FizzBuzzTest
+class FizzBuzzTest < Minitest::Test
def test_fizz_buzz: -> untyped
end
さらに、Steepfileにlibrary "minitest"
も追記してください。
target :lib do
check 'lib/fizz_buzz.rb'
check 'test/fizz_buzz_test.rb'
signature 'sig'
+ library "minitest"
end
こうすればSteep 0.51.0以上でもsteep checkが成功するはずです。
$ steep check
# Type checking files:
...................................................................................
No type error detected. 🫖
古い解決方法(非推奨)
本記事を最初に公開したときの解決方法です。
この方法でも対処できますが、わざわざ独自に型定義するメリットがないので推奨しません。
sig/fizz_buzz.rbs
に assert_equal
メソッドの型定義を追加する際、以下のように変更してください。
書籍に書かれているコード
# 省略
class FizzBuzzTest
def test_fizz_buzz: -> untyped
+ def assert_equal: (untyped, untyped) -> void
end
Steep 0.51.0以上に対応させる場合のコード
# 省略
+module Minitest
+ class Test
+ def assert_equal: (untyped, untyped) -> void
+ end
+end
-class FizzBuzzTest
+class FizzBuzzTest < Minitest::Test
def test_fizz_buzz: -> untyped
end
こうすればSteep 0.51.0以上でもsteep checkが成功するはずです。
$ steep check
# Type checking files:
...................................................................................
No type error detected. 🫖
PR:プロを目指す人のためのRuby入門 改訂2版をよろしくお願いします!
Rubyの基礎知識だけでなく、RBS/TypeProf/Steepを使ったRubyの型検査や、Ruby 2.7から導入されたパターンマッチなど、Rubyの新機能も学習できます!
「プロを目指す人のためのRuby入門 改訂2版」をみなさんよろしくお願いします🍒