mcpField
M
minitest-coder

minitest-coder

github.com/majesticlabs-devテスト・品質5053 回インストール7 週間前に更新
リポジトリ

minitest-coder について

minitest-coderは、RailsプロジェクトでMinitestのテストを書く方法をまとめたスキルガイドです。テスト形式、フィクスチャ、アサーション、カバレッジに加え、テストを整理しやすく保つパターンを扱います。

主な機能

  1. 01従来型とspec形式のテスト
  2. 02AAA構造と振る舞い重視のテスト
  3. 03Railsのテストファイル構成
  4. 04フィクスチャ、スタブ、モック
  5. 05アサーションとカバレッジの指針
  6. 06応用パターンとアンチパターン

活用シーン

  1. 01Railsのモデルやサービスのテスト作成
  2. 02シナリオに合うMinitest形式の選択
  3. 03テスト構成とカバレッジの確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/majesticlabs-dev/majestic-marketplace --skill minitest-coder

インストール後、Claude Code で/minitest-coderを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
advanced-patterns.md
anti-patterns.md
spec-patterns.md
testing-tips.md

詳細

Minitest コーダー

基本理念

  • AAA パターン:明確さを重視した Arrange-Act-Assert 構造
  • 実装より振る舞い:コードの実装方法ではなく、動作をテストします
  • 分離:テストはそれぞれ独立させます
  • 説明的な名前:テストの内容が明確に分かる名前を付けます
  • カバレッジ:正常系とエッジケースの両方をテストします
  • 高速なテスト:データベース操作を最小限にします
  • フィクスチャ:テストデータにはフィクスチャを使用します

Minitest のスタイル

スタイル最適な用途構文
従来型シンプルな単体テストtest "description"
Specコンテキストを含む複雑なシナリオlet/subjectを使ったdescribe/it
従来型スタイル
class UserTest < ActiveSupport::TestCase
  test "validates presence of name" do
    user = User.new
    assert_not user.valid?
    assert_includes user.errors[:name], "can't be blank"
  end
end
Spec スタイル
class UserTest < ActiveSupport::TestCase
  describe "#full_name" do
    subject { user.full_name }
    let(:user) { User.new(first_name: "Buffy", last_name:) }

    describe "with last name" do
      let(:last_name) { "Summers" }

      it "returns full name" do
        assert_equal "Buffy Summers", subject
      end
    end
  end
end

テストの構成

ファイル構成
  • test/models/ - モデルの単体テスト
  • test/services/ - サービスオブジェクトのテスト
  • test/integration/ - フルスタックテスト
  • test/mailers/ - メーラーのテスト
  • test/jobs/ - バックグラウンドジョブのテスト
  • test/fixtures/ - テストデータ
  • test/test_helper.rb - 設定
命名規則
  • アプリの構成を反映します:app/models/user.rb → test/models/user_test.rb
  • 完全修飾名前空間を使用します:class Users::ProfileServiceTest
  • require 'test_helper'は追加しないでください(自動で読み込まれます)

Spec スタイルのパターン

詳しい例はreferences/spec-patterns.mdを参照してください。

パターン用途
subject { ... }テスト対象のメソッド
let(:name) { ... }遅延評価されるデータ
describe "context"関連するテストをまとめます(最大3階層)
before { ... }複雑なセットアップ
describe "#process" do
  subject { processor.process }
  let(:processor) { OrderProcessor.new(order) }
  let(:order) { orders(:paid_order) }

  it "succeeds" do
    assert subject.success?
  end
end

フィクスチャ

# test/fixtures/users.yml
alice:
  name: Alice Smith
  email: [email protected]
  created_at: <%= 2.days.ago %>
class UserTest < ActiveSupport::TestCase
  fixtures :users

  test "validates uniqueness" do
    duplicate = User.new(email: users(:alice).email)
    assert_not duplicate.valid?
  end
end

モックとスタブ

詳しい例はreferences/spec-patterns.mdを参照してください。

メソッド目的
Object.stub :method, value戻り値をスタブします
Minitest::Mock.newメソッド呼び出しを検証します
test "processes payment" do
  PaymentGateway.stub :charge, true do
    processor = OrderProcessor.new(order)
    assert processor.process
  end
end

アサーション早見表

基本的なアサーション
# Boolean
assert user.valid?
assert_not user.admin?

# Equality
assert_equal "Alice", user.name
assert_nil user.deleted_at

# Collections
assert_includes users, admin_user
assert_empty order.items

# Exceptions
assert_raises ActiveRecord::RecordInvalid do
  user.save!
end
Rails のアサーション
# Changes
assert_changes -> { user.reload.status }, to: "active" do
  user.activate!
end

assert_difference "User.count", 1 do
  User.create(name: "Charlie")
end

# Responses
assert_response :success
assert_redirected_to user_path(user)

AAA パターン

test "processes refund" do
  # Arrange
  order = orders(:completed_order)
  original_balance = order.user.account_balance

  # Act
  result = order.process_refund

  # Assert
  assert result.success?
  assert_equal "refunded", order.reload.status
end

subject を使った Spec スタイル:

describe "#process_refund" do
  subject { order.process_refund }
  let(:order) { orders(:completed_order) }

  it "updates status" do
    subject
    assert_equal "refunded", order.reload.status
  end

  it "credits user" do
    assert_changes -> { order.user.reload.account_balance }, by: order.total do
      subject
    end
  end
end

テストカバレッジの基準

種類テスト対象
モデルバリデーション、関連付け、スコープ、コールバック、メソッド
サービス正常系、異常系、エッジケース、外部連携
コントローラーステータスコード、リダイレクト、パラメーターの処理
ジョブ実行、再試行ロジック、エラー処理
カバレッジの例
class UserTest < ActiveSupport::TestCase
  # Validations
  test "validates presence of name" do
    user = User.new(email: "[email protected]")
    assert_not user.valid?
    assert_includes user.errors[:name], "can't be blank"
  end

  # Methods
  describe "#full_name" do
    subject { user.full_name }
    let(:user) { User.new(first_name: "Alice", last_name: "Smith") }

    it "returns full name" do
      assert_equal "Alice Smith", subject
    end

    describe "without last name" do
      let(:user) { User.new(first_name: "Alice") }

      it "returns first name only" do
        assert_equal "Alice", subject
      end
    end
  end
end

高度なパターン

本番環境で検証済みの37signalsのパターンについては、references/advanced-patterns.mdを参照してください。

パターン解決する問題
Current.account フィクスチャマルチテナント環境での URL 分離
アサーション検証ヘルパー明確なメッセージを伴う早期失敗
決定的な UUID予測可能なフィクスチャの順序
VCR のタイムスタンプフィルタリング再利用可能な API カセット
スレッドベースの並行処理競合状態の検出
アダプター対応ヘルパーSQLite/MySQL との互換性

アンチパターン

詳しい例はreferences/anti-patterns.mdを参照してください。

アンチパターン問題点
require 'test_helper'自動で読み込まれます
3階層を超えるネスト出力が読みにくくなります
letの代わりに@ivarsを使う状態が漏洩します
subjectがないコードが重複します
assert x.include?(y)assert_includesを使ってください
プライベートメソッドのテスト実装との結合が強まります
フィクスチャを使わないテストが遅くなります

ベストプラクティスのチェックリスト

構成:

  • ファイル構成がアプリの構成を反映している
  • require 'test_helper' を追加していない
  • 完全修飾名前空間を使用している

スタイルの選択:

  • シンプルなテストには従来のスタイルを使用している
  • 複雑なコンテキストには Spec を使用している
  • ネストは最大 3 階層にしている

テストデータ:

  • フィクスチャを使用している(ファクトリーではなく)
  • 共通データに let を使用している
  • テスト対象のメソッドに subject を使用している

アサーション:

  • 適切なアサーションメソッドを使用している
  • Rails のヘルパー(assert_changes、assert_difference)を使用している
  • 実装ではなく動作をテストしている

カバレッジ:

  • 正常系をテストしている
  • 異常系をテストしている
  • エッジケースを網羅している

スタイルを選ぶ基準

従来のスタイル:シンプルなバリデーション、わかりやすいテスト、共通のセットアップがない場合

Spec:複数のコンテキスト、遅延評価が必要な場合、ネストしたシナリオ、再利用可能な subject がある場合

わかりやすさが向上する場合は、同じファイル内で両方を組み合わせることもできます。

コメント