test-prof 1.4.0.rc.2 → 1.4.0.rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/lib/test_prof/factory_default/factory_bot_patch.rb +9 -6
- data/lib/test_prof/tps_prof/profiler.rb +55 -0
- data/lib/test_prof/tps_prof/reporter/text.rb +48 -0
- data/lib/test_prof/tps_prof/rspec.rb +63 -0
- data/lib/test_prof/tps_prof.rb +46 -0
- data/lib/test_prof/version.rb +1 -1
- data/lib/test_prof.rb +1 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55eaa3ce2f79b5cae7992ea0e45a499c28ae1d301b2f7c9e34796d587c0e6090
|
4
|
+
data.tar.gz: 2f5a07b3a9c78304c054e025d0e785a253d310c354005ca767a7ea0674033e0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f26d5cdd70cd05d93fc0cc596302a72089c1718fd5b58084b5a219333ac6b0ba034d09c7a0e57840fa790f4198c7b8ba24f8dfdaa0d0b85a5f7404246b922b07
|
7
|
+
data.tar.gz: 22e6d9304af0c182f4bd1bf7d4b34a9bc8d5435b505100bebe9519cdac2f3d29ba47db3fe7de48179cc88c191cac3da531de4d3b6f506c2275dc52f45b832444
|
data/CHANGELOG.md
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "test_prof/factory_bot"
|
4
|
+
|
3
5
|
module TestProf
|
4
6
|
module FactoryDefault # :nodoc: all
|
5
7
|
module FactoryBotPatch
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
if defined?(TestProf::FactoryBot::FactoryRunner)
|
9
|
+
module RunnerExt
|
10
|
+
refine TestProf::FactoryBot::FactoryRunner do
|
11
|
+
attr_reader :name, :traits, :overrides
|
12
|
+
end
|
9
13
|
end
|
10
|
-
end
|
11
14
|
|
12
|
-
|
15
|
+
using RunnerExt
|
16
|
+
end
|
13
17
|
|
14
18
|
module StrategyExt
|
15
19
|
def association(runner)
|
@@ -53,7 +57,6 @@ module TestProf
|
|
53
57
|
end
|
54
58
|
|
55
59
|
def self.patch
|
56
|
-
require "test_prof/factory_bot"
|
57
60
|
return unless defined?(TestProf::FactoryBot)
|
58
61
|
|
59
62
|
TestProf::FactoryBot::Syntax::Methods.include SyntaxExt
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_prof/utils/sized_ordered_set"
|
4
|
+
|
5
|
+
module TestProf
|
6
|
+
module TPSProf
|
7
|
+
class Profiler
|
8
|
+
attr_reader :top_count, :groups, :total_count, :total_time, :threshold
|
9
|
+
|
10
|
+
def initialize(top_count, threshold: 10)
|
11
|
+
@threshold = threshold
|
12
|
+
@top_count = top_count
|
13
|
+
@total_count = 0
|
14
|
+
@total_time = 0.0
|
15
|
+
@groups = Utils::SizedOrderedSet.new(top_count, sort_by: :tps)
|
16
|
+
end
|
17
|
+
|
18
|
+
def group_started(id)
|
19
|
+
@current_group = id
|
20
|
+
@examples_count = 0
|
21
|
+
@examples_time = 0.0
|
22
|
+
@group_started_at = TestProf.now
|
23
|
+
end
|
24
|
+
|
25
|
+
def group_finished(id)
|
26
|
+
return unless @examples_count >= threshold
|
27
|
+
|
28
|
+
# Context-time
|
29
|
+
group_time = (TestProf.now - @group_started_at) - @examples_time
|
30
|
+
run_time = @examples_time + group_time
|
31
|
+
|
32
|
+
groups << {
|
33
|
+
id: id,
|
34
|
+
run_time: run_time,
|
35
|
+
group_time: group_time,
|
36
|
+
count: @examples_count,
|
37
|
+
tps: -(@examples_count / run_time).round(2)
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def example_started(id)
|
42
|
+
@example_started_at = TestProf.now
|
43
|
+
end
|
44
|
+
|
45
|
+
def example_finished(id)
|
46
|
+
@examples_count += 1
|
47
|
+
@total_count += 1
|
48
|
+
|
49
|
+
time = (TestProf.now - @example_started_at)
|
50
|
+
@examples_time += time
|
51
|
+
@total_time += time
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_prof/ext/float_duration"
|
4
|
+
require "test_prof/ext/string_truncate"
|
5
|
+
|
6
|
+
module TestProf
|
7
|
+
module TPSProf
|
8
|
+
module Reporter
|
9
|
+
class Text
|
10
|
+
include Logging
|
11
|
+
using FloatDuration
|
12
|
+
using StringTruncate
|
13
|
+
|
14
|
+
def print(profiler)
|
15
|
+
groups = profiler.groups
|
16
|
+
|
17
|
+
total_tps = (profiler.total_count / profiler.total_time).round(2)
|
18
|
+
|
19
|
+
msgs = []
|
20
|
+
|
21
|
+
msgs <<
|
22
|
+
<<~MSG
|
23
|
+
Total TPS (tests per second): #{total_tps}
|
24
|
+
|
25
|
+
Top #{profiler.top_count} slowest suites by TPS (tests per second) (min examples per group: #{profiler.threshold}):
|
26
|
+
|
27
|
+
MSG
|
28
|
+
|
29
|
+
groups.each do |group|
|
30
|
+
description = group[:id].top_level_description
|
31
|
+
location = group[:id].metadata[:location]
|
32
|
+
time = group[:run_time]
|
33
|
+
group_time = group[:group_time]
|
34
|
+
count = group[:count]
|
35
|
+
tps = -group[:tps]
|
36
|
+
|
37
|
+
msgs <<
|
38
|
+
<<~GROUP
|
39
|
+
#{description.truncate} (#{location}) – #{tps} TPS (#{time.duration} / #{count}), group time: #{group_time.duration}
|
40
|
+
GROUP
|
41
|
+
end
|
42
|
+
|
43
|
+
log :info, msgs.join
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TestProf
|
4
|
+
module TPSProf
|
5
|
+
class RSpecListener # :nodoc:
|
6
|
+
include Logging
|
7
|
+
|
8
|
+
NOTIFICATIONS = %i[
|
9
|
+
example_group_started
|
10
|
+
example_group_finished
|
11
|
+
example_started
|
12
|
+
example_finished
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
attr_reader :reporter, :profiler
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@profiler = Profiler.new(TPSProf.config.top_count, threshold: TPSProf.config.threshold)
|
19
|
+
@reporter = TPSProf.config.reporter
|
20
|
+
|
21
|
+
log :info, "TPSProf enabled (top-#{TPSProf.config.top_count})"
|
22
|
+
end
|
23
|
+
|
24
|
+
def example_group_started(notification)
|
25
|
+
return unless notification.group.top_level?
|
26
|
+
profiler.group_started notification.group
|
27
|
+
end
|
28
|
+
|
29
|
+
def example_group_finished(notification)
|
30
|
+
return unless notification.group.top_level?
|
31
|
+
profiler.group_finished notification.group
|
32
|
+
end
|
33
|
+
|
34
|
+
def example_started(notification)
|
35
|
+
profiler.example_started notification.example
|
36
|
+
end
|
37
|
+
|
38
|
+
def example_finished(notification)
|
39
|
+
profiler.example_finished notification.example
|
40
|
+
end
|
41
|
+
|
42
|
+
def print
|
43
|
+
reporter.print(profiler)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Register TPSProf listener
|
50
|
+
TestProf.activate("TPS_PROF") do
|
51
|
+
RSpec.configure do |config|
|
52
|
+
listener = nil
|
53
|
+
|
54
|
+
config.before(:suite) do
|
55
|
+
listener = TestProf::TPSProf::RSpecListener.new
|
56
|
+
config.reporter.register_listener(
|
57
|
+
listener, *TestProf::TPSProf::RSpecListener::NOTIFICATIONS
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
config.after(:suite) { listener&.print }
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_prof/tps_prof/profiler"
|
4
|
+
require "test_prof/tps_prof/reporter/text"
|
5
|
+
|
6
|
+
module TestProf
|
7
|
+
# TPSProf shows top-N example group based on their tests-per-second value.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
#
|
11
|
+
# TPS_PROF=10 rspec ...
|
12
|
+
#
|
13
|
+
module TPSProf
|
14
|
+
class Configuration
|
15
|
+
attr_accessor :top_count, :threshold, :reporter
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@top_count = ENV["TPS_PROF"].to_i
|
19
|
+
@top_count = 10 if @top_count == 1
|
20
|
+
@threshold = ENV.fetch("TPS_PROF_MIN", 10).to_i
|
21
|
+
@reporter = resolve_reporter(ENV["TPS_PROF_FORMAT"])
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def resolve_reporter(format)
|
27
|
+
# TODO: support other formats
|
28
|
+
TPSProf::Reporter::Text.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def config
|
34
|
+
@config ||= Configuration.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def configure
|
38
|
+
yield config
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
require "test_prof/tps_prof/rspec" if TestProf.rspec?
|
45
|
+
# TODO: Minitest support
|
46
|
+
# require "test_prof/tps_prof/minitest" if TestProf.minitest?
|
data/lib/test_prof/version.rb
CHANGED
data/lib/test_prof.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test-prof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.0.rc.
|
4
|
+
version: 1.4.0.rc.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Dementyev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -219,6 +219,10 @@ files:
|
|
219
219
|
- lib/test_prof/tag_prof/printers/simple.rb
|
220
220
|
- lib/test_prof/tag_prof/result.rb
|
221
221
|
- lib/test_prof/tag_prof/rspec.rb
|
222
|
+
- lib/test_prof/tps_prof.rb
|
223
|
+
- lib/test_prof/tps_prof/profiler.rb
|
224
|
+
- lib/test_prof/tps_prof/reporter/text.rb
|
225
|
+
- lib/test_prof/tps_prof/rspec.rb
|
222
226
|
- lib/test_prof/utils.rb
|
223
227
|
- lib/test_prof/utils/html_builder.rb
|
224
228
|
- lib/test_prof/utils/rspec.rb
|