### Initial `let_it_be` Example Source: https://test-prof.evilmartians.io/llms-full.txt Illustrates the initial setup with `let!` for creating test data, which is then improved by `let_it_be`. ```ruby describe BeatleWeightedSearchQuery do let!(:paul) { create(:beatle, name: "Paul") } let!(:ringo) { create(:beatle, name: "Ringo") } let!(:george) { create(:beatle, name: "George") } let!(:john) { create(:beatle, name: "John") } specify { expect(subject.call("john")).to contain_exactly(john) } # and more examples here end ``` -------------------------------- ### RSpec before_all setup with TestProf Source: https://test-prof.evilmartians.io/llms-full.txt This demonstrates the recommended `before_all` usage with TestProf in RSpec. It runs setup code once per example group within a transaction. ```ruby describe BeatleWeightedSearchQuery do before_all do @paul = create(:beatle, name: "Paul") # ... end # ... end ``` -------------------------------- ### RSpec before(:all) setup Source: https://test-prof.evilmartians.io/llms-full.txt Using `before(:all)` in RSpec for setup. Be aware that this requires careful database cleaning as transactions are not automatically rolled back per example. ```ruby describe BeatleWeightedSearchQuery do before(:all) do @paul = create(:beatle, name: "Paul") # ... end # ... end ``` -------------------------------- ### Basic before(:each) setup in RSpec Source: https://test-prof.evilmartians.io/llms-full.txt This is a standard RSpec setup using `before(:each)` to create instances before each test. It's less efficient for common setup across many tests. ```ruby describe BeatleWeightedSearchQuery do before(:each) do @paul = create(:beatle, name: "Paul") @ringo = create(:beatle, name: "Ringo") @george = create(:beatle, name: "George") @john = create(:beatle, name: "John") end # and about 15 examples here end ``` -------------------------------- ### Measure Reusable Setup Time Source: https://test-prof.evilmartians.io/llms-full.txt Use `RD_PROF=1` to measure time spent in `let`/`before` compared to actual example time using RSpecDissect. ```sh RD_PROF=1 bin/rspec ``` -------------------------------- ### Configure EventProf with Environment Variable for Examples Source: https://test-prof.evilmartians.io/llms-full.txt Alternatively, set the EVENT_PROF_EXAMPLES=1 environment variable to profile individual test examples. ```sh EVENT_PROF_EXAMPLES=1 ``` -------------------------------- ### MemoryProf Example Output Source: https://test-prof.evilmartians.io/llms-full.txt Example output of MemoryProf showing RSS usage for groups and examples. ```sh [TEST PROF INFO] MemoryProf results Final RSS: 673KB Top 5 groups (by RSS): AnswersController (./spec/controllers/answers_controller_spec.rb:3) – +80KB (13.50%) QuestionsController (./spec/controllers/questions_controller_spec.rb:3) – +32KB (9.08%) CommentsController (./spec/controllers/comments_controller_spec.rb:3) – +16KB (3.27%) Top 5 examples (by RSS): destroys question (./spec/controllers/questions_controller_spec.rb:38) – +144KB (24.38%) change comments count (./spec/controllers/comments_controller_spec.rb:7) – +120KB (20.00%) change Votes count (./spec/shared_examples/controllers/voted_examples.rb:23) – +90KB (16.36%) change Votes count (./spec/shared_examples/controllers/voted_examples.rb:23) – +64KB (12.86%) fails (./spec/shared_examples/controllers/invalid_examples.rb:3) – +32KB (5.00%) ``` -------------------------------- ### FactoryDoctor Report Example Source: https://test-prof.evilmartians.io/llms-full.txt An example output from FactoryDoctor, highlighting potentially inefficient test examples and the time wasted. ```sh [TEST PROF INFO] FactoryDoctor report Total (potentially) bad examples: 2 Total wasted time: 00:13.165 User (./spec/models/user_spec.rb:3) (3 records created, 00:00.628) validates name (./spec/user_spec.rb:8) – 1 record created, 00:00.114 validates email (./spec/user_spec.rb:8) – 2 records created, 00:00.514 ``` -------------------------------- ### Example RSpecDissect Output Source: https://test-prof.evilmartians.io/llms-full.txt This output shows the total time spent in `before(:each)` hooks and `let` declarations, along with the top slowest example groups and `let` usage within those groups. ```sh [TEST PROF INFO] RSpecDissect enabled Total time: 25:14.870 Total `before(:each)` time: 14:36.482 Total `let` time: 19:20.259 Top 5 slowest suites (by `before(:each)` time): Webhooks::DispatchTransition (./spec/services/webhooks/dispatch_transition_spec.rb:3) – 00:29.895 of 00:33.706 (327) FunnelsController (./spec/controllers/funnels_controller_spec.rb:3) – 00:22.117 of 00:43.649 (133) ApplicantsController (./spec/controllers/applicants_controller_spec.rb:3) – 00:21.220 of 00:41.407 (222) BookedSlotsController (./spec/controllers/booked_slots_controller_spec.rb:3) – 00:15.729 of 00:27.893 (50) Analytics::Wor...rsion::Summary (./spec/services/analytics/workflow_conversion/summary_spec.rb:3) – 00:15.383 of 00:15.914 (12) Top 5 slowest suites (by `let` time): FunnelsController (./spec/controllers/funnels_controller_spec.rb:3) – 00:38.532 of 00:43.649 (133) ↳ user – 3 ↳ funnel – 2 ApplicantsController (./spec/controllers/applicants_controller_spec.rb:3) – 00:33.252 of 00:41.407 (222) ↳ user – 10 ↳ funnel – 5 ↳ applicant – 2 Webhooks::DispatchTransition (./spec/services/webhooks/dispatch_transition_spec.rb:3) – 00:30.320 of 00:33.706 (327) ↳ user – 30 BookedSlotsController (./spec/controllers/booked_slots_controller_spec.rb:3) – 00:25.710 of 00:27.893 e(50) ↳ user – 21 ↳ stage – 14 AvailableSlotsController (./spec/controllers/available_slots_controller_spec.rb:3) – 00:18.481 of 00:23.366 (85) ↳ user – 15 ↳ stage – 10 ``` -------------------------------- ### Add StackProf Gem Source: https://test-prof.evilmartians.io/llms-full.txt Install the `stackprof` gem, which is recommended for general profiling. ```sh bundle add stackprof ``` -------------------------------- ### Install Profiling Gems Source: https://test-prof.evilmartians.io/llms-full.txt Install StackProf or Vernier gems using Bundler. These are recommended for general profiling of Ruby applications. ```sh bundle add stackprof ``` ```sh # or bundle add vernier ``` -------------------------------- ### Using `before_all` for Test Data Setup Source: https://test-prof.evilmartians.io/llms-full.txt An alternative approach using `before_all` to set up shared test data, which requires using instance variables and defining all data at once. ```ruby describe BeatleWeightedSearchQuery do before_all do @paul = create(:beatle, name: "Paul") # ... end specify { expect(subject.call("joh")).to contain_exactly(@john) } # ... end ``` -------------------------------- ### AnyFixture DSL Setup for Minitest Source: https://test-prof.evilmartians.io/llms-full.txt Include the AnyFixture DSL in a base Minitest class to use the `fixture` method and callbacks. ```ruby require "test_prof/any_fixture/dsl" class MyBaseTestCase < Minitest::Test include TestProf::AnyFixture::DSL end ``` -------------------------------- ### Minitest integration with TestProf BeforeAll Source: https://test-prof.evilmartians.io/llms-full.txt This example shows how to integrate `before_all` with Minitest. It requires including `TestProf::BeforeAll::Minitest` and defining the `before_all` block. ```ruby require "test_prof/recipes/minitest/before_all" class MyBeatlesTest < Minitest::Test include TestProf::BeforeAll::Minitest before_all do @paul = create(:beatle, name: "Paul") @ringo = create(:beatle, name: "Ringo") @george = create(:beatle, name: "George") @john = create(:beatle, name: "John") end # define tests which could access the object defined within `before_all` end ``` -------------------------------- ### TagProf Output Example (with SQL events) Source: https://test-prof.evilmartians.io/llms-full.txt Example output of TagProf report when profiling SQL events, showing time spent on 'sql.active_record' per type. ```sh [TEST PROF INFO] TagProf report for type type time sql.active_record total %total %time avg request 00:04.808 00:01.402 42 33.87 54.70 00:00.114 controller 00:02.855 00:00.921 42 33.87 32.48 00:00.067 model 00:01.127 00:00.446 40 32.26 12.82 00:00.028 ``` -------------------------------- ### Factory Stack Example Source: https://test-prof.evilmartians.io/llms-full.txt Illustrates a sequence of factory creation calls and their resulting stack. Wider columns indicate higher frequency of a stack's appearance. ```ruby factory :comment do answer author end factory :answer do question author end factory :question do author end create(:comment) #=> creates 5 records # And the corresponding stack is: # [:comment, :answer, :question, :author, :author, :author] ``` -------------------------------- ### Minitest Setup for AnyFixture Source: https://test-prof.evilmartians.io/llms-full.txt Require AnyFixture and ensure database cleanup after each test run by calling TestProf::AnyFixture.clean at exit. ```ruby require "test_prof/any_fixture" at_exit { TestProf::AnyFixture.clean } ``` -------------------------------- ### Using Fixture Callbacks Source: https://test-prof.evilmartians.io/llms-full.txt Define callbacks to run before or after fixtures are reset, useful for custom cleanup or setup. ```ruby before_fixtures_reset { Post.delete_all } after_fixtures_reset { Post.delete_all } ``` -------------------------------- ### TagProf Output Example (Basic) Source: https://test-prof.evilmartians.io/llms-full.txt Example output of TagProf report showing test statistics grouped by type, including time, count, and average. ```sh [TEST PROF INFO] TagProf report for type type time total %total %time avg request 00:04.808 42 33.87 54.70 00:00.114 controller 00:02.855 42 33.87 32.48 00:00.067 model 00:01.127 40 32.26 12.82 00:00.028 ``` -------------------------------- ### Enable Per-Example Profiling in EventProf Source: https://test-prof.evilmartians.io/llms-full.txt Set `config.per_example = true` to profile individual examples instead of just top-level groups. Alternatively, use the `EVENT_PROF_EXAMPLES=1` environment variable. ```ruby TestProf::EventProf.configure do |config| config.per_example = true end ``` -------------------------------- ### Run FactoryDoctor with FactoryAllStub Stamp Source: https://test-prof.evilmartians.io/llms-full.txt Use this command to run FactoryDoctor and automatically mark all problematic examples with the `factory:stub` stamp, facilitating quick fixes. ```sh # Run FactoryDoctor and mark all offensive examples with factory:stub FDOC=1 FDOC_STAMP=factory:stub rspec ./spec/models ``` -------------------------------- ### Register Dump with Before Hook for Tenant Creation Source: https://test-prof.evilmartians.io/llms-full.txt Use a 'before' hook to perform actions like creating a tenant before a fixture dump is processed. This example ensures a 'test' tenant exists. ```ruby TestProf::AnyFixture.register_dump( "account", before: proc do begin Apartment::Tenant.create("test") rescue nil end Apartment::Tenant.create("test") end ) do # ... end ``` -------------------------------- ### Use FactoryAllStub with RSpec Examples Source: https://test-prof.evilmartians.io/llms-full.txt Mark specific RSpec examples or groups with `factory: :stub` to enforce the `build_stubbed` strategy, overriding the default `create` behavior. ```ruby describe "User" do let(:user) { create(:user) } it "is valid", factory: :stub do # use `build_stubbed` instead of `create` expect(user).to be_valid end end ``` -------------------------------- ### TagProf Minitest Unknown Grouping Example Source: https://test-prof.evilmartians.io/llms-full.txt Example output for Minitest when TagProf cannot determine test file locations, showing an '__unknown__' group. ```sh [TEST PROF INFO] TagProf report for type type time sql.active_record total %total %time avg __unknown__ 00:04.808 00:01.402 42 33.87 54.70 00:00.114 controller 00:02.855 00:00.921 42 33.87 32.48 00:00.067 model 00:01.127 00:00.446 40 32.26 12.82 00:00.028 ``` -------------------------------- ### Profile Individual Examples with StackProf Source: https://test-prof.evilmartians.io/llms-full.txt Use the :sprof metadata tag in RSpec examples to profile them individually. Note that this does not work when global (per-suite) profiling is active. ```ruby it "is doing heavy stuff", :sprof do # ... end ``` -------------------------------- ### Define Factories with Associations Source: https://test-prof.evilmartians.io/llms-full.txt Example of defining factories with associations using FactoryBot. ```ruby factory :account do end factory :user do account end factory :project do account user end factory :task do account project user end ``` -------------------------------- ### Basic `let_it_be` Usage in Tests Source: https://test-prof.evilmartians.io/llms-full.txt Example of using `let_it_be` within a test suite after requiring the recipe. ```ruby describe MySuperDryService do let_it_be(:user) { create(:user) } # ... end ``` -------------------------------- ### Set Factory Default Methods Source: https://test-prof.evilmartians.io/llms-full.txt Examples of using `set_factory_default` to define default records for factories. ```ruby let(:user) { create(:user) } before { FactoryBot.set_factory_default(:user, user) } # You can also set the default factory with traits FactoryBot.set_factory_default([:user, :admin], admin) # Or (since v1.4) FactoryBot.set_factory_default(:user, :admin, admin) # You can also register a default record for specific attribute overrides Fabricate.set_fabricate_default(:post, post, state: "draft") ``` -------------------------------- ### Define Factories with Fabrication Source: https://test-prof.evilmartians.io/llms-full.txt Example of defining factories with associations using Fabrication. ```ruby Fabricator(:account) do end Fabricator(:user) do account end ``` -------------------------------- ### Collect SQL Queries with EventProf (Minitest) Source: https://test-prof.evilmartians.io/llms-full.txt Use the EVENT_PROF environment variable to collect SQL query statistics for every suite and example when running Minitest. ```sh EVENT_PROF='sql.active_record' rake test ``` -------------------------------- ### Minitest Setup for AnyFixture Source: https://test-prof.evilmartians.io/llms-full.txt When using AnyFixture with Minitest, ensure you manually clean the database after each test run by calling `TestProf::AnyFixture.clean` at exit. ```ruby # test_helper.rb require "test_prof/any_fixture" at_exit { TestProf::AnyFixture.clean } ``` -------------------------------- ### AnyFixture DSL Setup for RSpec Source: https://test-prof.evilmartians.io/llms-full.txt Include the AnyFixture DSL in RSpec configuration to use the `fixture` method and callbacks. ```ruby require "test_prof/any_fixture/dsl" RSpec.configure do |config| config.include TestProf::AnyFixture::DSL end ``` -------------------------------- ### Integrate EventProf with RSpecStamp Source: https://test-prof.evilmartians.io/llms-full.txt Use `EVENT_PROF` and `EVENT_PROF_STAMP` environment variables to mark slow examples with custom tags. This example marks slow SQL events. ```sh EVENT_PROF="sql.active_record" EVENT_PROF_STAMP="slow:sql" rspec ... ``` -------------------------------- ### Ensuring multiple database connections are loaded Source: https://test-prof.evilmartians.io/llms-full.txt To use `before_all` with multiple database connections, ensure all relevant connection classes are loaded before tests run. This example shows loading `ApplicationRecord` and `AccountsRecord`. ```ruby class Users < AccountsRecord # ... end class Articles < ApplicationRecord # ... end ``` ```ruby # Ensure connection classes are loaded ApplicationRecord AccountsRecord ``` -------------------------------- ### Explicitly Tagging for Frost Mode Source: https://test-prof.evilmartians.io/llms-full.txt You can tag individual contexts or examples with `:let_it_be_frost` to enable the frost mode for that specific scope. ```ruby context "with frost mode enabled", let_it_be_frost: true do # ... end ``` -------------------------------- ### Register a Fixture with ActiveRecord Source: https://test-prof.evilmartians.io/llms-full.txt Register a fixture named 'account' using plain ActiveRecord to create the data. This demonstrates direct database manipulation for fixture setup. ```ruby TestProf::AnyFixture.register(:account) do # ... # or with plain old AR Account.create!(name: "test") end ``` -------------------------------- ### FactoryBot: Validate Name Presence (Good) Source: https://test-prof.evilmartians.io/llms-full.txt This example demonstrates an optimized test using FactoryBot's `build_stubbed` method, avoiding unnecessary database writes. ```ruby # with FactoryBot/FactoryGirl it "validates name presence" do user = build_stubbed(:user) user.name = "" expect(user).not_to be_valid end ``` -------------------------------- ### Configure Strict Mode Thresholds Source: https://test-prof.evilmartians.io/llms-full.txt In strict mode, configure environment variables to set thresholds for failing builds. These include maximum examples, maximum time, and minimum TPS. ```sh TPS_PROF=strict TPS_PROF_MAX_EXAMPLES=50 rspec ``` ```sh TPS_PROF=strict TPS_PROF_MAX_TIME=30 rspec ``` ```sh TPS_PROF=strict TPS_PROF_MIN_TPS=5 rspec ``` ```sh TPS_PROF=strict TPS_PROF_MIN_TPS=5 TPS_PROF_MAX_TIME=30 rspec ``` -------------------------------- ### Generate StackProf Reports with Suffixes Source: https://test-prof.evilmartians.io/llms-full.txt Use the TEST_PROF_REPORT environment variable to add custom suffixes to report filenames, useful for comparing different test setups. This example shows generating reports with and without 'bootsnap'. ```sh # Generate first report using `-with-bootsnap` suffix $ TEST_STACK_PROF=boot TEST_PROF_REPORT=with-bootsnap bundle exec rake $ #=> StackProf report generated: tmp/test_prof/stack-prof-report-wall-raw-boot-with-bootsnap.dump # Assume that you disabled bootsnap and want to generate a new report $ TEST_STACK_PROF=boot TEST_PROF_REPORT=no-bootsnap bundle exec rake $ #=> StackProf report generated: tmp/test_prof/stack-prof-report-wall-raw-boot-no-bootsnap.dump ``` -------------------------------- ### Configure EventProf Ranking Source: https://test-prof.evilmartians.io/llms-full.txt Use the `EVENT_PROF_RANK` environment variable to sort profiling statistics by event count or time spent. Example shown for sorting by count. ```sh EVENT_PROF_RANK=count EVENT_PROF='instantiation.active_record' be rspec ``` -------------------------------- ### Show EventProf CLI Help Source: https://test-prof.evilmartians.io/llms-full.txt Display the list of possible command-line options for EventProf. ```sh ruby test/my_super_test.rb --help ``` -------------------------------- ### Display Minitest Help with EventProf Options Source: https://test-prof.evilmartians.io/llms-full.txt To see a list of available options for EventProf when running Minitest, use the `--help` flag. ```sh # Show the list of possible options: ruby test/my_super_test.rb --help ``` -------------------------------- ### Enable Global StackProf Profiling Source: https://test-prof.evilmartians.io/llms-full.txt Activate StackProf profiling for your entire test suite by setting the TEST_STACK_PROF environment variable. This is a simple way to start profiling. ```sh TEST_STACK_PROF=1 bundle exec rake test ``` -------------------------------- ### Implement Custom Database Adapter for BeforeAll Source: https://test-prof.evilmartians.io/llms-full.txt Create a custom adapter by implementing `begin_transaction` and `rollback_transaction` methods. Configure BeforeAll to use your custom adapter. ```ruby class MyDBAdapter # before_all adapters must implement two methods: # - begin_transaction # - rollback_transaction def begin_transaction # ... end def rollback_transaction # ... end end # And then set adapter for `BeforeAll` module TestProf::BeforeAll.adapter = MyDBAdapter.new ``` -------------------------------- ### Profile Individual RSpec Examples with RubyProf Source: https://test-prof.evilmartians.io/llms-full.txt Profile specific RSpec examples by adding the :rprof tag to the example. Note that per-example profiling is not compatible with global profiling. ```ruby it "is doing heavy stuff", :rprof do # ... end ``` -------------------------------- ### Tag Slow Factory Tests with EventProf and EVEN_PROF_STAMP Source: https://test-prof.evilmartians.io/llms-full.txt Automatically tag the slowest examples based on factory creation time. Use EVENT_PROF=factory.create and EVEN_PROF_STAMP=slow:factory to mark these tests for further analysis. ```sh EVENT_PROF=factory.create EVEN_PROF_STAMP=slow:factory bin/rspec spec/models ``` -------------------------------- ### Mark Slowest Examples with Custom Tag Source: https://test-prof.evilmartians.io/llms-full.txt Automatically mark the slowest examples with a custom tag like `slow:factory` in RSpec. ```sh EVENT_PROF=factory.create EVENT_PROF_STAMP=slow:factory bin/rspec spec/models ``` -------------------------------- ### Registering SQL Dump for Test Data Source: https://test-prof.evilmartians.io/llms-full.txt Use `register_dump` to optimize test data setup by generating an SQL dump. This is useful for large datasets or performance-critical tests. The block is executed only if the SQL dump is missing, and subsequent runs restore data from the dump. ```ruby RSpec.shared_context "account", account: true do # You should call AnyFixture outside of transaction to re-use the same # data between examples before(:all) do # The block is called once per test run (similary to #register) TestProf::AnyFixture.register_dump("account") do # Do anything here, AnyFixture keeps track of affected DB tables # For example, you can use factories here account = FactoryGirl.create(:account, name: "test") # or with Fabrication account = Fabricate(:account, name: "test") # or with plain old AR account = Account.create!(name: "test") # updates are also tracked account.update!(tag: "sql-dump") end end # Here, we MUST use a custom way to retrieve a record: since we restore the data # from a plain SQL dump, we have no knowledge of Ruby objects let(:account) { Account.find_by!(name: "test") } end ``` -------------------------------- ### Using FactoryDefault with `let_it_be` Source: https://test-prof.evilmartians.io/llms-full.txt Defaults created within `before_all` and `let_it_be` are not reset after each example, but only at the end of the corresponding example group. RSpec only. ```ruby # Using with `before_all` / `let_it_be` # Defaults created within `before_all` and `let_it_be` are not reset after each example, but only at the end of the corresponding example group. So, it's possible to call `create_default` within `let_it_be` without any additional configuration. **RSpec only** **IMPORTANT:** You must load FactoryDefault after loading BeforeAll to make this feature work. **NOTE**. Regular `before(:all)` callbacks are not supported. ``` -------------------------------- ### Profile Application Boot with StackProf Source: https://test-prof.evilmartians.io/llms-full.txt Profile the application boot process by setting TEST_STACK_PROF to 'boot' and specifying a test file. This helps identify performance bottlenecks during application initialization. ```sh # pick some random spec (1 is enough) $ TEST_STACK_PROF=boot bundle exec rspec ./spec/some_spec.rb ``` -------------------------------- ### Configure Factory Logging Source: https://test-prof.evilmartians.io/llms-full.txt Use `factory.create` report to narrow down scope to top files when using factories. ```sh EVENT_PROF=factory.create bin/rspec spec/models ``` -------------------------------- ### Minitest: Ignore Specific Example Source: https://test-prof.evilmartians.io/llms-full.txt Shows how to ignore a Minitest example from FactoryDoctor's analysis using the `fd_ignore` method within the test. ```ruby # won't be reported as offense it "is ignored" do fd_ignore @user.name = "" refute @user.valid? end ``` -------------------------------- ### Initialize FactoryAllStub Source: https://test-prof.evilmartians.io/llms-full.txt Call this method to initialize FactoryAllStub, injecting its custom logic into the FactoryBot generator. This is required for manual control. ```ruby TestProf::FactoryAllStub.init ``` -------------------------------- ### Profile Individual Examples with Vernier Source: https://test-prof.evilmartians.io/llms-full.txt Use the :vernier metadata tag in RSpec examples to profile them individually. This feature is not available when global profiling is active. ```ruby it "is doing heavy stuff", :vernier do # ... end ``` -------------------------------- ### RSpec Example with Aggregate Failures Source: https://test-prof.evilmartians.io/llms-full.txt This RSpec example demonstrates how to use `:aggregate_failures` to collect all failures within a test. It also shows how to explicitly check headers and status codes. ```ruby it "returns the second page", :aggregate_failures do is_expected.to be_success is_expected.to have_header("X-TOTAL-PAGES", 10) is_expected.to have_header("X-NEXT-PAGE", 2) expect(subject.status).to eq(200) end ``` -------------------------------- ### Create Default Shortcut Source: https://test-prof.evilmartians.io/llms-full.txt Using `create_default` as a shortcut for `create` and `set_factory_default`. ```ruby # FactoryBot#create_default(...) / Fabricate.create_default(...) # is a shortcut for `create` + `set_factory_default`. ``` -------------------------------- ### FactoryDefault Cleanup Behavior Source: https://test-prof.evilmartians.io/llms-full.txt Defaults are cleaned up after each example by default when using `test_prof/recipes/rspec/factory_default`. ```ruby # IMPORTANT: Defaults are **cleaned up after each example** by default (i.e., when using `test_prof/recipes/rspec/factory_default`). ``` -------------------------------- ### Using FactoryDefault for Associations Source: https://test-prof.evilmartians.io/llms-full.txt Demonstrates using `create_default` to simplify association creation with FactoryDefault. ```ruby describe "PATCH #update" do let(:account) { create_default(:account) } let(:project) { create_default(:project) } let(:task) { create(:task) } # and if we need more projects, users, tasks with the same parent record, # we just write let(:another_project) { create(:project) } # uses the same account let(:another_task) { create(:task) } # uses the same account it "works" do patch :update, id: task.id, task: {completed: "t"} expect(response).to be_success end end ``` -------------------------------- ### Configure Global Before and After Dump Hooks Source: https://test-prof.evilmartians.io/llms-full.txt Set up global hooks that execute before or after dump operations. The 'before_dump' hook receives dump information and an import flag, while 'after_dump' also provides dump details and can check for success. ```ruby TestProf::AnyFixture.configure do |config| config.before_dump do |dump:, import:| # dump is an object containing information about the dump (e.g., dump.digest) # import is true if we're restoring a dump and false otherwise # do something end config.after_dump do |dump:, import:| # ... end end ``` -------------------------------- ### Run Specific File with EventProf CLI (Minitest) Source: https://test-prof.evilmartians.io/llms-full.txt Execute a specific test file using the --event-prof CLI option to collect SQL query statistics. ```sh ruby test/my_super_test.rb --event-prof=sql.active_record ``` -------------------------------- ### Get Factory Default Method Source: https://test-prof.evilmartians.io/llms-full.txt Retrieving the default value for a factory using `get_factory_default`. ```ruby # FactoryBot#get_factory_default(factory) / Fabricate.get_fabricate_default(factory) – retrieves the default value for `factory` (since v1.4). # This method also supports traits admin = FactoryBot.get_factory_default(:user, :admin) ``` -------------------------------- ### Minitest MemoryProf CLI Configuration Top Count Source: https://test-prof.evilmartians.io/llms-full.txt Configure the number of top examples/groups to display for Minitest using CLI options. ```sh # Run a specific file using CLI option ruby test/my_super_test.rb --mem-prof=rs --mem-prof-top-count=10 ``` -------------------------------- ### Initializing FactoryAllStub Source: https://test-prof.evilmartians.io/llms-full.txt Code to initialize FactoryAllStub, which injects custom logic into FactoryBot's generator to enable all-stub mode. ```ruby TestProf::FactoryAllStub.init ``` -------------------------------- ### Handling Traits with FactoryDefault Source: https://test-prof.evilmartians.io/llms-full.txt Demonstrates how FactoryDefault interacts with traits and how to configure it to preserve traits. ```ruby factory :comment do user end factory :post do association :user, factory: %i[user able_to_post] end factory :view do association :user, factory: %i[user unable_to_post_only_view] end # If there is a default value for the `user` factory, it's gonna be used independently of traits. This may break your logic. # To prevent this, configure FactoryDefault to preserve traits: # Globally TestProf::FactoryDefault.configure do |config| config.preserve_traits = true end # or in-place create_default(:user, preserve_traits: true) # Creating a default with trait works as follows: # Create a default with trait user = create_default(:user_poster, :able_to_post) # When an association has no traits specified, the default with trait is used create(:comment).user == user #=> true # When an association has the matching trait specified, the default is used, too create(:post).user == user #=> true ``` -------------------------------- ### Activate FactoryProf with Variations and Limit Source: https://test-prof.evilmartians.io/llms-full.txt Run FactoryProf with variations enabled and a limit on the number of variations displayed by setting FPROF=1 and FPROF_VARIATIONS_LIMIT=N environment variables. ```sh FPROF=1 FPROF_VARIATIONS_LIMIT=5 rspec ``` ```sh FPROF=1 FPROF_VARIATIONS_LIMIT=5 bundle exec rake test ``` -------------------------------- ### Integrating FactoryDoctor with RSpecStamp Source: https://test-prof.evilmartians.io/llms-full.txt Example of using FactoryDoctor with RSpecStamp to automatically tag potentially bad test cases with a custom tag. ```sh FDOC=1 FDOC_STAMP="fdoc:consider" rspec ... ``` -------------------------------- ### Enabling AnyFixture DSL with Refinement Source: https://test-prof.evilmartians.io/llms-full.txt Use `using TestProf::AnyFixture::DSL` to enable syntactic sugar for defining fixtures and callbacks, allowing the use of `fixture` and `before_fixtures_reset`/`after_fixtures_reset` methods. ```ruby require "test_prof/any_fixture/dsl" # Enable DSL using TestProf::AnyFixture::DSL # and then you can use `fixture` method (which is just an alias for `TestProf::AnyFixture.register`) before(:all) { fixture(:account) } # You can also use it to fetch the record (instead of storing it in instance variable) let(:account) { fixture(:account) } # You can just use `before_fixtures_reset` or `after_fixtures_reset` callbacks before_fixtures_reset { Post.delete_all } after_fixtures_reset { Post.delete_all } ``` -------------------------------- ### Fabrication: Ignore Specific Example Source: https://test-prof.evilmartians.io/llms-full.txt Demonstrates how to ignore a specific test case from FactoryDoctor's analysis by adding the `:fd_ignore` tag. ```ruby # won't be reported as offense it "is ignored", :fd_ignore do user = create(:user) user.name = "" expect(user).not_to be_valid end ``` -------------------------------- ### Add ruby-prof to Gemfile Source: https://test-prof.evilmartians.io/llms-full.txt Ensure the ruby-prof gem is installed by adding it to your Gemfile. It's recommended to require it only for development and test environments. ```ruby # Gemfile group :development, :test do gem "ruby-prof", ">= 1.4.0", require: false end ``` -------------------------------- ### AnyFixture DSL for Fixture Definition Source: https://test-prof.evilmartians.io/llms-full.txt Use the optional DSL for a more concise way to define fixtures. Enable the DSL using `using TestProf::AnyFixture::DSL` and then use the `fixture` method as an alias for `TestProf::AnyFixture.register`. ```ruby require "test_prof/any_fixture/dsl" # Enable DSL using TestProf::AnyFixture::DSL # and then you can use `fixture` method (which is just an alias for `TestProf::AnyFixture.register`) before(:all) { fixture(:account) } # You can also use it to fetch the record (instead of storing it in instance variable) let(:account) { fixture(:account) } ``` -------------------------------- ### Ignore Groups or Examples with TPSProf Source: https://test-prof.evilmartians.io/llms-full.txt Exclude specific RSpec groups from TPSProf tracking by adding the `tps_prof: :ignore` metadata to the group definition. ```ruby RSpec.describe "SlowButOk", tps_prof: :ignore do # ... end ``` -------------------------------- ### Create Default Factory Object Source: https://test-prof.evilmartians.io/llms-full.txt Use `create_default` as a shortcut for `create` and `set_factory_default`. ```ruby create_default(:user) ``` -------------------------------- ### Configure AnyFixture CLI Import Source: https://test-prof.evilmartians.io/llms-full.txt Determine whether AnyFixture should attempt to use command-line tools (like psql or sqlite3) for restoring dumps, or use ActiveRecord instead. Using CLI tools prevents tracking affected tables for cleanup. ```ruby TestProf::AnyFixture.configure do |config| # ... # Whether to try using CLI tools such as psql or sqlite3 to restore dumps or not (and use ActiveRecord instead) config.import_dump_via_cli = false end ``` -------------------------------- ### Use Refind Modifier with LetItBe Source: https://test-prof.evilmartians.io/llms-full.txt Employ the `refind: true` modifier to hard-reload records, ensuring they are fetched from the database in their pristine state for each example. ```ruby # You can also specify refind: true option to hard-reload the record let_it_be(:user, refind: true) { create(:user) } # it is almost equal to before_all { @user = create(:user) } let(:user) { User.find(@user.id) } ``` -------------------------------- ### Configuring AnyFixture Dumps Directory and Import Behavior Source: https://test-prof.evilmartians.io/llms-full.txt Customize AnyFixture's behavior by setting the dumps directory, configuring which queries to include in dumps, and choosing whether to use CLI tools for restoring dumps. ```ruby TestProf::AnyFixture.configure do |config| # Where to store dumps (by default, TestProf.artifact_path + '/any_dumps') config.dumps_dir = "any_dumps" # Include mathing queries into a dump (in addition to INSERT/UPDATE/DELETE queries) config.dump_matching_queries = /^$/ # Whether to try using CLI tools such as psql or sqlite3 to restore dumps or not (and use ActiveRecord instead) config.import_dump_via_cli = false end ``` -------------------------------- ### FactoryBot: Validate Name Presence (Bad) Source: https://test-prof.evilmartians.io/llms-full.txt This example shows an inefficient test using FactoryBot where a user record is created in the database unnecessarily. ```ruby # with FactoryBot/FactoryGirl it "validates name presence" do user = create(:user) user.name = "" expect(user).not_to be_valid end ``` -------------------------------- ### Enable Rails Fixtures in BeforeAll Hooks Source: https://test-prof.evilmartians.io/llms-full.txt Opt-in to using fixtures within `before_all` hooks by setting `setup_fixture: true` or globally via `TestProf::BeforeAll.configure`. ```ruby before_all(setup_fixtures: true) do @user = users(:john) @post = create(:post, user: user) end ``` ```ruby TestProf::BeforeAll.configure do |config| config.setup_fixtures = true end ``` -------------------------------- ### Fabrication: Validate Name Presence (Bad) Source: https://test-prof.evilmartians.io/llms-full.txt This example demonstrates an inefficient test using Fabrication where a user record is created in the database unnecessarily. ```ruby it "validates name presence" do user = Fabricate.build(:user) user.name = "" expect(user).not_to be_valid end ``` -------------------------------- ### Manually Enable/Disable Shared Connection Source: https://test-prof.evilmartians.io/llms-full.txt Use these methods to programmatically control the shared connection mode. This is useful for specific test setups or debugging. ```ruby TestProf::ActiveRecordSharedConnection.enable! ``` ```ruby TestProf::ActiveRecordSharedConnection.disable! ``` -------------------------------- ### Profile Application Boot with Vernier Source: https://test-prof.evilmartians.io/llms-full.txt Profile the application boot process with Vernier by setting TEST_VERNIER to 'boot' and specifying a test file. This is useful for diagnosing startup performance issues. ```sh # pick some random spec (1 is enough) TEST_VERNIER=boot bundle exec rspec ./spec/some_spec.rb ``` -------------------------------- ### Configure FactoryDefault to Report Summary Source: https://test-prof.evilmartians.io/llms-full.txt Enable the reporting of FactoryDefault usage statistics globally. This helps in understanding how often default factories are being utilized. ```ruby TestProf::FactoryDefault.configure do |config| config.report_summary = true # Report stats prints the detailed usage information (including summary) config.report_stats = true end ``` -------------------------------- ### Enable Transactional Fixtures in RSpec Rails Source: https://test-prof.evilmartians.io/llms-full.txt To ensure database rollback between RSpec examples, enable `use_transactional_fixtures` in your `spec/rails_helper.rb`. This is crucial for isolated test runs. ```ruby RSpec.configure do |config| config.use_transactional_fixtures = true # RSpec takes care to use `use_transactional_tests` or `use_transactional_fixtures` depending on the Rails version used end ``` -------------------------------- ### Use RSpecDissect with RSpecStamp Source: https://test-prof.evilmartians.io/llms-full.txt Integrate RSpecDissect with RSpecStamp to automatically tag slow examples. Set `RD_PROF_STAMP` to a desired tag name when running RSpec with `RD_PROF=1`. ```sh RD_PROF=1 RD_PROF_STAMP="slow" rspec ... ``` -------------------------------- ### Activate EventProf with Minitest Source: https://test-prof.evilmartians.io/llms-full.txt For Minitest 6+, first load the TestProf plugin in your test helper. Then, use the `EVENT_PROF` environment variable set to the event name to collect profiling data. ```sh # Collect SQL queries stats for every suite and example EVENT_PROF='sql.active_record' rake test ``` -------------------------------- ### Run Sampling Tests Source: https://test-prof.evilmartians.io/llms-full.txt Run multiple subsets of tests with `SAMPLE=100` to reveal application-wide problems and analyze the obtained flamegraphs. ```sh SAMPLE=100 bin/rails test ``` -------------------------------- ### Use Reload Modifier with LetItBe Source: https://test-prof.evilmartians.io/llms-full.txt Utilize the `reload: true` modifier to ensure objects are re-initialized for each example, preventing state leakage. This is useful for ActiveRecord instances. ```ruby # Use reload: true option to reload user object (assuming it's an instance of ActiveRecord) # for every example let_it_be(:user, reload: true) { create(:user) } # it is almost equal to before_all { @user = create(:user) } let(:user) { @user.reload } ``` -------------------------------- ### Configure TestProf Global Settings Source: https://test-prof.evilmartians.io/llms-full.txt Set the directory for artifacts, enable unique filenames and color output, and specify where logs should be written. You can also provide a custom logger instance. ```ruby TestProf.configure do |config| # the directory to put artifacts (reports) in ('tmp/test_prof' by default) config.output_dir = "tmp/test_prof" # use unique filenames for reports (by simply appending current timestamp) config.timestamps = true # color output config.color = true # where to write logs (defaults) config.output = $stdout # alternatively, you can specify a custom logger instance config.logger = MyLogger.new end ``` -------------------------------- ### Measure Factory Default Summary Source: https://test-prof.evilmartians.io/llms-full.txt Use `FACTORY_DEFAULT_SUMMARY=1` to measure the impact of adding `create_default` and observe the summary of hits and misses. ```sh FACTORY_DEFAULT_SUMMARY=1 bin/rspec --tag slow:factory ``` -------------------------------- ### Activating FactoryDoctor with Minitest CLI Source: https://test-prof.evilmartians.io/llms-full.txt Demonstrates how to activate FactoryDoctor for Minitest using the command-line option `--factory-doctor`. ```sh ruby ... --factory-doctor ``` -------------------------------- ### Minitest MemoryProf CLI Option Source: https://test-prof.evilmartians.io/llms-full.txt Run a specific Minitest file using the --mem-prof CLI option. ```sh # Run a specific file using CLI option ruby test/my_super_test.rb --mem-prof=rss ``` -------------------------------- ### Collect SQL Queries with EventProf (RSpec) Source: https://test-prof.evilmartians.io/llms-full.txt Use the EVENT_PROF environment variable to collect SQL query statistics for every suite and example when running RSpec. ```sh EVENT_PROF='sql.active_record' rspec ... ``` -------------------------------- ### Configure BeforeAll Transaction Hooks Source: https://test-prof.evilmartians.io/llms-full.txt Register callbacks to execute before or after a transaction begins or is rolled back. Use the `configure` block to define these hooks. ```ruby TestProf::BeforeAll.configure do |config| config.before(:begin) do # do something before transaction opens end # after(:begin) is also available config.after(:rollback) do # do something after transaction closes end # before(:rollback) is also available end ``` -------------------------------- ### Registering and Using Fixtures with DSL Source: https://test-prof.evilmartians.io/llms-full.txt Use the `fixture` method to register a fixture with a block that creates the record. It can also be used to fetch the registered fixture. ```ruby before(:all) { fixture(:account) { create(:account) } } let(:account) { fixture(:account) } ``` -------------------------------- ### Modifying objects in before_all Source: https://test-prof.evilmartians.io/llms-full.txt When objects created in `before_all` are modified in tests, their state can become dependent on the test order. Reloading the record for every example can solve this. ```ruby before_all do @user = create(:user) end let(:user) { @user } it "when user is admin" do # we modified our object in-place! user.update!(role: 1) expect(user).to be_admin end it "when user is regular" do # now @user's state depends on the order of specs! expect(user).not_to be_admin end ``` ```ruby before_all do @user = create(:user) end # Note, that @user.reload may not be enough, # 'cause it doesn't reset associations let(:user) { User.find(@user.id) } ``` ```ruby # or with Minitest def setup @user = User.find(@user.id) end ``` -------------------------------- ### Bad Practice: Unnecessary Database Creation Source: https://test-prof.evilmartians.io/llms-full.txt Demonstrates an inefficient test pattern using `create` which performs database operations and callbacks when only validation is needed. ```ruby # with FactoryBot/FactoryGirl it "validates name presence" do user = create(:user) user.name = "" expect(user).not_to be_valid end # with Fabrication it "validates name presence" do user = Fabricate(:user) user.name = "" expect(user).not_to be_valid end ``` -------------------------------- ### Disable 'let' Stats in RSpecDissect Source: https://test-prof.evilmartians.io/llms-full.txt To disable the collection and display of `let` statistics, configure `TestProf::RSpecDissect` within your RSpec setup to set `let_stats_enabled` to `false`. ```ruby TestProf::RSpecDissect.configure do |config| config.let_stats_enabled = false end ``` -------------------------------- ### Run Minitest with EventProf CLI Option Source: https://test-prof.evilmartians.io/llms-full.txt Alternatively, you can use CLI options with Minitest to activate EventProf. This allows specifying the event to profile directly when running tests. ```sh # Run a specific file using CLI option ruby test/my_super_test.rb --event-prof=sql.active_record ``` -------------------------------- ### Enable Per-Example Logging with RSpec Tag Source: https://test-prof.evilmartians.io/llms-full.txt Activate verbose logging for a specific RSpec example or group by adding the ':log' tag. This is useful for debugging individual tests. ```ruby # Add the tag and you will see a lot of interesting stuff in your console it "does smthng weird", :log do # ... end # or for the group describe "GET #index", :log do # ... end ``` -------------------------------- ### Integrate RSpecDissect with RSpecStamp Source: https://test-prof.evilmartians.io/llms-full.txt Combine RSpecDissect with RSpecStamp to automatically tag slow example groups. Set `RD_PROF_STAMP` to a desired tag name to mark the slowest groups. ```sh RD_PROF=1 RD_PROF_STAMP="slow" rspec ... ``` -------------------------------- ### Require FactoryAllStub in RSpec Source: https://test-prof.evilmartians.io/llms-full.txt Include this line in your `spec_helper.rb` or `rails_helper.rb` to automatically initialize FactoryAllStub and enable the `factory: :stub` shared context. ```ruby require "test_prof/recipes/rspec/factory_all_stub" ``` -------------------------------- ### Activate EventProf with RSpec Source: https://test-prof.evilmartians.io/llms-full.txt To activate EventProf for RSpec, set the `EVENT_PROF` environment variable to the desired event name. This will collect statistics for all suites and examples related to that event. ```sh # Collect SQL queries stats for every suite and example EVENT_PROF='sql.active_record' rspec ... ```