Act: Execute the code under test
total = cart.calculate_total
Assert: Verify expected outcomes
assert_equal 0, total
Separates setup, execution, and verification into distinct phases
When: Action or trigger
when_the_user_calculates_total
Then: Expected outcome
then_the_total_should_be_zero
Emphasizes business behavior over technical implementation
def save(key, value)
@data[key] = value
end
def find(key)
@data[key]
end
end
In-memory database, fake file system
def teardown
@database.clear
end
Bad: Unclear purpose
test_user_reg_1
Avoid: Multiple unrelated assertions
test_userCreation
user = create_user
assert_equal "member", user.role
assert_not_nil user.email
assert_true user.active
end
Bad
test_userValidation_withValidAge_succeeds
user = User.new(age: 25)
assert user.valid?
end
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: testing-patterns-33description: This skill should be used when the user asks to "write tests", "test strategy", "coverage", "unit test", "integration test", or needs testing guidance. Provides testing methodology and patterns. Use when this capability is needed.4---56<purpose>7Provide testing patterns and strategies for comprehensive test coverage and maintainable test suites.8</purpose>910<concept name="unit">11<description>Test individual functions/methods in isolation</description>12<scope>Single function, class, or module</scope>13<characteristics>Fast, isolated, deterministic</characteristics>14<when>Business logic, utility functions, transformations</when>15</concept>1617<concept name="integration">18<description>Test interaction between components</description>19<scope>Multiple components working together</scope>20<characteristics>Slower, may use real dependencies</characteristics>21<when>API endpoints, database operations, service interactions</when>22</concept>2324<concept name="e2e">25<description>Test complete user workflows</description>26<scope>Full application stack</scope>27<characteristics>Slowest, tests real user scenarios</characteristics>28<when>Critical user journeys, smoke tests</when>29</concept>3031<pattern name="arrange_act_assert">32<description>Three-phase test structure for clear test organization</description>33<example>34<test_phase>Arrange: Set up test data and preconditions</test_phase>35user = User.new(name: "John")36cart = ShoppingCart.new(user)3738<test_phase>Act: Execute the code under test</test_phase>3940total = cart.calculate_total4142<test_phase>Assert: Verify expected outcomes</test_phase>4344assert_equal 0, total45</example>46<note>Separates setup, execution, and verification into distinct phases</note>47</pattern>4849<pattern name="given_when_then">50<description>BDD-style test structure focusing on behavior</description>51<example>52<bdd_step>Given: Initial context (preconditions)</bdd_step>53given_a_user_with_an_empty_cart5455<bdd_step>When: Action or trigger</bdd_step>5657when_the_user_calculates_total5859<bdd_step>Then: Expected outcome</bdd_step>6061then_the_total_should_be_zero62</example>63<note>Emphasizes business behavior over technical implementation</note>64</pattern>6566<pattern name="stub">67<description>Provide canned responses for dependencies</description>68<example>69api_client = stub(70 fetch_user: { id: 1, name: "John" }71)72</example>73<use_case>Replace slow/unreliable dependencies</use_case>74</pattern>7576<pattern name="mock">77<description>Verify interactions occurred with dependencies</description>78<example>79email_service = mock()80email_service.expect(:send_email, args: ["user@example.com", "Welcome"])81user_service.register(email_service)82email_service.verify83</example>84<use_case>Ensure methods called with correct arguments</use_case>85</pattern>8687<pattern name="spy">88<description>Record calls while using real implementation</description>89<example>90logger = spy(Logger.new)91service.process(logger)92assert_called logger, :log, with: "Processing complete"93</example>94<use_case>Verify side effects without changing behavior</use_case>95</pattern>9697<pattern name="fake">98<description>Working implementation suitable for testing</description>99<example>100class FakeDatabase101 def initialize102 @data = {}103 end104105def save(key, value)106@data[key] = value107end108109def find(key)110@data[key]111end112end113</example>114<use_case>In-memory database, fake file system</use_case>115</pattern>116117<pattern name="descriptive_naming">118<description>Test names that clearly describe scenario and outcome</description>119<example>120test_calculateTotal_withEmptyCart_returnsZero121test_calculateTotal_withMultipleItems_returnsSumOfPrices122test_calculateTotal_withDiscount_appliesDiscountCorrectly123</example>124<note>Format: test_[method]_[scenario]_[expected_result]</note>125</pattern>126127<pattern name="should_naming">128<description>BDD-style naming that reads like natural language</description>129<example>130calculateTotal_should_returnZero_when_cartIsEmpty131calculateTotal_should_applyDiscount_when_couponIsValid132calculateTotal_should_throwError_when_pricesAreNegative133</example>134<note>Format: [method]_should_[expected_behavior]_when_[condition]</note>135</pattern>136137<best_practices>138<practice priority="critical">139<name>Test happy path first</name>140<description>Start with the normal, expected flow before edge cases</description>141<example>142test_userLogin_withValidCredentials_succeeds143test_userLogin_withInvalidPassword_fails144test_userLogin_withLockedAccount_fails145</example>146</practice>147148<practice priority="critical">149<name>Test edge cases</name>150<description>Test boundary conditions and limits</description>151<example>152Empty inputs, maximum values, null values, zero values, negative numbers153</example>154</practice>155156<practice priority="critical">157<name>Test error cases</name>158<description>Verify error handling paths work correctly</description>159<example>160Invalid inputs, network failures, permission errors, timeout scenarios161</example>162</practice>163164<practice priority="high">165<name>Isolate tests</name>166<description>Each test should be independent</description>167<example>168<note>Use setup/teardown to reset state</note>169def setup170 @database = TestDatabase.new171 @service = UserService.new(@database)172end173174def teardown175@database.clear176end177</example>178</practice>179180<practice priority="high">181<name>Make tests readable</name>182<description>Tests serve as documentation</description>183<example>184<note>Good: Clear and descriptive</note>185test_userRegistration_withExistingEmail_returnsError186187<note>Bad: Unclear purpose</note>188189test_user_reg_1190</example>191</practice>192193<practice priority="high">194<name>One assertion per concept</name>195<description>Each test should verify one logical concept</description>196<example>197<note>Good: Single concept</note>198test_userCreation_setsDefaultRole199 user = create_user200 assert_equal "member", user.role201end202203<note>Avoid: Multiple unrelated assertions</note>204205test_userCreation206user = create_user207assert_equal "member", user.role208assert_not_nil user.email209assert_true user.active210end211</example>212</practice>213214<practice priority="medium">215<name>Use test fixtures and factories</name>216<description>Extract common test data setup</description>217<example>218<note>Create reusable test data</note>219def create_test_user(overrides = {})220 defaults = {221 name: "Test User",222 email: "test@example.com",223 role: "member"224 }225 User.new(defaults.merge(overrides))226end227</example>228</practice>229230<practice priority="medium">231<name>Avoid magic numbers</name>232<description>Use named constants for test values</description>233<example>234<good_example>Good</good_example>235VALID_USER_AGE = 25236MINIMUM_AGE = 18237test_userValidation_withValidAge_succeeds238 user = User.new(age: VALID_USER_AGE)239 assert user.valid?240end241242<bad_example>Bad</bad_example>243244test_userValidation_withValidAge_succeeds245user = User.new(age: 25)246assert user.valid?247end248</example>249</practice>250251<practice priority="medium">252<name>Test corner cases</name>253<description>Test unusual combinations and scenarios</description>254<example>255Concurrent access, timezone edge cases, leap years, DST transitions256</example>257</practice>258</best_practices>259260<concept name="line_coverage">261<description>Percentage of code lines executed during tests</description>262<guidance>Measures which lines of code are exercised</guidance>263</concept>264265<concept name="branch_coverage">266<description>Percentage of code branches (if/else, switch) taken during tests</description>267<guidance>More thorough than line coverage as it measures decision paths</guidance>268</concept>269270<concept name="function_coverage">271<description>Percentage of functions/methods called during tests</description>272<guidance>Identifies untested functions</guidance>273</concept>274275<rules priority="standard">276<rule>Aim for high coverage but prioritize meaningful tests over coverage numbers</rule>277<rule>80%+ coverage is a good target for critical code paths</rule>278<rule>100% coverage does not guarantee bug-free code</rule>279<rule>Focus on testing behavior, not achieving coverage metrics</rule>280</rules>281282<anti_patterns>283<avoid name="testing_implementation">284<description>Testing implementation details instead of behavior</description>285<instead>Focus on testing observable behavior and outcomes, not internal implementation details. Test what the code does, not how it does it.</instead>286</avoid>287288<avoid name="excessive_mocking">289<description>Over-mocking dependencies throughout test suites</description>290<instead>Use real implementations where practical; excessive mocking often indicates poor design. Only mock external dependencies or slow operations.</instead>291</avoid>292293<avoid name="flaky_tests">294<description>Tests that sometimes pass and sometimes fail</description>295<instead>Ensure tests are deterministic by controlling time, randomness, and async operations. Use fixed timestamps, seeded random generators, and proper async handling.</instead>296</avoid>297298<avoid name="slow_tests">299<description>Tests that take too long to run</description>300<instead>Use unit tests for fast feedback; reserve slow integration/e2e tests for critical paths. Unit tests should run in milliseconds, not seconds.</instead>301</avoid>302303<avoid name="test_interdependence">304<description>Tests that depend on execution order or shared state</description>305<instead>Make each test independent with proper setup/teardown and isolated state. Each test should create its own test data.</instead>306</avoid>307</anti_patterns>308309---310> Converted and distributed by [TomeVault](https://tomevault.io/claim/mtaku3) — claim your Tome and manage your conversions.311<!-- tomevault:4.0:skill_md:2026-04-13 -->