【チェリー本】steep checkで"Ruby::UnknownConstant"というエラーが発生する場合の対処法

## 発生する問題
拙著「[プロを目指す人のためのRuby入門 改訂2版](https://gihyo.jp/book/2021/978-4-297-12437-3)（通称 チェリー本）」の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以上だとこの問題が発生します。
どうやらこの仕様変更が影響しているようです。

https://github.com/soutaro/steep/pull/524

書籍の執筆時は0.44.1が最新バージョンだったため、この問題は発生しませんでした。

@soutaro さんいわく、

> 0.51よりも前のバージョンだと、知らない定数がいたら黙って `untyped` にしていた（ように見えた）のが、きちんと「知らない定数があるよ」と報告するためのエラーを導入した

とのことです（[ruby-jp](https://ruby-jp.github.io/)のやりとりより）。

### 参考：バージョンの確認方法
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用の型情報がデフォルトで提供されるようになりました（[参考](https://github.com/ruby/rbs/blob/master/CHANGELOG.md#260-2022-06-22)）。このため、`sig/fizz_buzz.rbs` に `assert_equal` メソッドの型定義を追加する代わりに以下の修正を行ってください。

### 書籍に書かれているコード

以下の変更ではSteep 0.51.0以上でエラーが出ます。

```diff_ruby:sig/fizz_buzz.rbs
 # 省略
 class FizzBuzzTest
   def test_fizz_buzz: -> untyped
+  def assert_equal: (untyped, untyped) -> void
 end
```

### Steep 0.51.0以上に対応させる場合のコード

Steep 0.51.0以上では以下のように変更してください。

```diff_ruby:sig/fizz_buzz.rbs
 # 省略
-class FizzBuzzTest
+class FizzBuzzTest < Minitest::Test
   def test_fizz_buzz: -> untyped
 end
```

さらに、Steepfileに`library "minitest"`も追記してください。

```diff:Steepfile
 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. 🫖
```

## 古い解決方法（非推奨）

:::note warn
本記事を最初に公開したときの解決方法です。
この方法でも対処できますが、わざわざ独自に型定義するメリットがないので推奨しません。
:::


`sig/fizz_buzz.rbs` に `assert_equal` メソッドの型定義を追加する際、以下のように変更してください。

### 書籍に書かれているコード

```diff_ruby:sig/fizz_buzz.rbs
 # 省略
 class FizzBuzzTest
   def test_fizz_buzz: -> untyped
+  def assert_equal: (untyped, untyped) -> void
 end
```

### Steep 0.51.0以上に対応させる場合のコード

```diff_ruby:sig/fizz_buzz.rbs
 # 省略
+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版」をみなさんよろしくお願いします🍒

https://gihyo.jp/book/2021/978-4-297-12437-3