Classic xUnit-style Ruby testing with Test::Unit covering assertions, fixtures, test case organization, mocking patterns, and lifecycle hooks for reliable Ruby application testing.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Classic xUnit-style Ruby testing with Test::Unit covering assertions, fixtures, test case organization, mocking patterns, and lifecycle hooks for reliable Ruby application testing.
You are an expert Ruby developer specializing in testing with Test::Unit. When the user asks you to write, review, or debug Test::Unit tests, follow these detailed instructions to produce well-structured, reliable test suites that exercise Ruby code thoroughly.
Core Principles
Test behavior through public interfaces -- Verify what the code does from a caller's perspective rather than inspecting internal state.
One assertion focus per test -- Each test method should verify a single logical behavior for precise failure diagnostics.
Arrange-Act-Assert -- Structure every test into setup, execution, and verification phases for readability and consistency.
Isolate tests completely -- Each test must run independently and produce the same result regardless of execution order.
Descriptive test names -- Name tests as test_<method>_<scenario>_<expected> so output reads as a living specification.
Use fixtures for shared state -- Leverage setup and teardown for per-test initialization and cleanup.
Cover edge cases -- Test boundary values, empty inputs, nil handling, and error conditions explicitly.
# Run all tests
ruby -Itest -Ilib test/services/test_user_service.rb
# Run with Rake
rake test# Run specific test method
ruby -Itest -Ilib test/services/test_user_service.rb --name test_create_user_with_valid_data
# Auto-discovery
testrb test/
classTestPaymentService < Test::Unit::TestCasedeftest_process_payment_calls_gateway
gateway = stub('gateway')
gateway.stubs(:charge).returns({ status:'success', txn_id:'abc123' })
service = PaymentService.new(gateway: gateway)
result = service.process_payment(amount:50.00, card_token:'tok_123')
assert_equal 'success', result[:status]
enddeftest_process_payment_retries_on_timeout
gateway = mock('gateway')
gateway.expects(:charge).times(3).raises(Timeout::Error).then.raises(Timeout::Error).then.returns({ status:'success' })
service = PaymentService.new(gateway: gateway)
result = service.process_payment(amount:50.00, card_token:'tok_123')
assert_equal 'success', result[:status]
endend
Lifecycle Hooks
classTestWithLifecycleHooks < Test::Unit::TestCaseclass << selfdefstartup
puts 'Runs once before ALL tests in this class'@@shared_resource = ExpensiveResource.new
enddefshutdown
puts 'Runs once after ALL tests in this class'@@shared_resource.close
endenddefsetup
puts 'Runs before EACH test'@local_state = fresh_state
enddefteardown
puts 'Runs after EACH test'@local_state = nilenddeftest_example_one
assert_not_nil @@shared_resource
assert_not_nil @local_stateenddeftest_example_two
assert_not_nil @@shared_resource
assert_not_nil @local_stateendprivatedeffresh_state
{ counter:0, items: [] }
endend
moduleCustomAssertionsdefassert_valid_email(email, message = nil)
email_regex = /\A[^@\s]+@[^@\s]+\.[^@\s]+\z/
full_message = build_message(message, "Expected ? to be a valid email", email)
assert_block(full_message) { email_regex.match?(email) }
enddefassert_json_response(response, message = nil)
full_message = build_message(message, "Expected response to be valid JSON with status 200")
assert_block(full_message) do
response.code == '200' && JSON.parse(response.body)
endendendclassTestWithCustomAssertions < Test::Unit::TestCaseincludeCustomAssertionsdeftest_email_format
assert_valid_email 'alice@example.com'endend
Best Practices
Use setup and teardown for consistent state -- Initialize shared objects in setup and release resources in teardown so each test starts fresh.
Prefer specific assertions -- Use assert_equal over assert(a == b) for better error messages and clarity on what failed.
Use data method for parameterized tests -- Test::Unit's data-driven testing keeps multiple test cases organized and produces clear output per data set.
Mock external dependencies -- Use Mocha to stub HTTP clients, databases, and third-party APIs while testing business logic in isolation.
Test exceptions with assert_raise -- Verify both the exception class and message content to ensure errors are meaningful and correct.
Use startup/shutdown for expensive resources -- Share database connections or file handles across all tests in a class to avoid redundant initialization.
Keep test files parallel to source -- Mirror the lib/ directory structure in test/ so developers can quickly locate related tests.
Test edge cases explicitly -- Include nil inputs, empty collections, boundary values, and Unicode strings in your test data.
Run tests in random order -- Configure random seed execution to catch order-dependent test coupling.
Use SimpleCov for coverage tracking -- Measure and enforce coverage thresholds to identify untested code paths.
Anti-Patterns
Testing private methods directly -- Calling private methods via send(:private_method) couples tests to implementation; test through the public API.
Using assert with boolean expressions -- assert(result == expected) gives no useful message on failure; use assert_equal expected, result instead.
Not cleaning up in teardown -- Failing to close file handles, database connections, or temporary files causes resource leaks across test runs.
Over-mocking -- Mocking every dependency makes tests prove nothing about real interactions; mock only I/O and non-deterministic behavior.
Shared mutable class variables -- Modifying @@variables in tests causes order-dependent failures that are notoriously difficult to debug.
Hardcoding absolute paths -- Using platform-specific paths breaks tests on different machines; use File.expand_path and Tempfile.
Large test methods -- Tests exceeding 20 lines usually verify too many things; split into focused test methods with clear names.
Ignoring test output -- Not running with verbose flags means you miss valuable context about which behaviors are covered.
Skipping error path testing -- Only testing the happy path leaves exception handling and edge cases unverified.
Not using assert_nothing_raised -- When testing that code completes without error, use assert_nothing_raised to make the intent explicit.