1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
|
# frozen_string_literal: true
require "fileutils"
require "test_prof/version"
require "test_prof/logging"
require "test_prof/utils"
# Ruby applications tests profiling tools.
#
# Contains tools to analyze factories usage, integrate with Ruby profilers,
# profile your examples using ActiveSupport notifications (if any) and
# statically analyze your code with custom RuboCop cops.
#
# Example usage:
#
# require 'test_prof'
#
# # Activate a tool by providing environment variable, e.g.
# TEST_RUBY_PROF=1 rspec ...
#
# # or manually in your code
# TestProf::RubyProf.run
#
# See other modules for more examples.
module TestProf
class << self
include Logging
def config
@config ||= Configuration.new
end
def configure
yield config
end
# Returns true if we're inside RSpec
def rspec?
defined?(RSpec::Core)
end
# Returns true if we're inside Minitest
def minitest?
defined?(Minitest)
end
# Returns the current process time
def now
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
# Require gem and shows a custom
# message if it fails to load
def require(gem_name, msg = nil)
Kernel.require gem_name
block_given? ? yield : true
rescue LoadError
log(:error, msg) if msg
false
end
# Run block only if provided env var is present and
# equal to the provided value (if any).
# Contains workaround for applications using Spring.
def activate(env_var, val = nil)
if defined?(::Spring::Application)
notify_spring_detected
::Spring.after_fork do
activate!(env_var, val) do
notify_spring_activate env_var
yield
end
end
else
activate!(env_var, val) { yield }
end
end
# Return absolute path to asset
def asset_path(filename)
::File.expand_path(filename, ::File.join(::File.dirname(__FILE__), "..", "assets"))
end
# Return a path to store artifact
def artifact_path(filename)
create_artifact_dir
with_timestamps(
::File.join(
config.output_dir,
with_report_suffix(
filename
)
)
)
end
def create_artifact_dir
FileUtils.mkdir_p(config.output_dir)[0]
end
private
def activate!(env_var, val)
yield if ENV[env_var] && (val.nil? || val === ENV[env_var])
end
def with_timestamps(path)
return path unless config.timestamps?
timestamps = "-#{now.to_i}"
"#{path.sub(/\.\w+$/, "")}#{timestamps}#{::File.extname(path)}"
end
def with_report_suffix(path)
return path if config.report_suffix.nil?
"#{path.sub(/\.\w+$/, "")}-#{config.report_suffix}#{::File.extname(path)}"
end
def notify_spring_detected
return if instance_variable_defined?(:@spring_notified)
log :info, "Spring detected"
@spring_notified = true
end
def notify_spring_activate(env_var)
log :info, "Activating #{env_var} with `Spring.after_fork`"
end
end
# TestProf configuration
class Configuration
attr_accessor :output, # IO to write output messages.
:color, # Whether to colorize output or not
:output_dir, # Directory to store artifacts
:timestamps, # Whether to use timestamped names for artifacts,
:report_suffix # Custom suffix for reports/artifacts
def initialize
@output = $stdout
@color = true
@output_dir = "tmp/test_prof"
@timestamps = false
@report_suffix = ENV["TEST_PROF_REPORT"]
end
def color?
color == true
end
def timestamps?
timestamps == true
end
end
end
require "test_prof/ruby_prof"
require "test_prof/stack_prof"
require "test_prof/event_prof"
require "test_prof/factory_doctor"
require "test_prof/factory_prof"
require "test_prof/rspec_stamp"
require "test_prof/tag_prof"
require "test_prof/rspec_dissect"
require "test_prof/factory_all_stub"
|