test-prof 1.4.0.rc.2 → 1.4.0.rc.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24fc1f10f015aca5ffcaa3fa9568bd397f31d4a23c043d2b2781a1ebb2158a9e
4
- data.tar.gz: fe79040f5a8455525e42d8b282cd6a48ff9d1be63ee9de2975c25f561419d7d9
3
+ metadata.gz: 55eaa3ce2f79b5cae7992ea0e45a499c28ae1d301b2f7c9e34796d587c0e6090
4
+ data.tar.gz: 2f5a07b3a9c78304c054e025d0e785a253d310c354005ca767a7ea0674033e0f
5
5
  SHA512:
6
- metadata.gz: 29e36545b692685977c96fd0f489a71189ee3472f2e1a09896c34635d43f01fe60de58a52a6bbec9f0352668057a4178d2f1f15aa454f94cafc4a87a933150ed
7
- data.tar.gz: a80468699056d18f936e53b7474f9082b39105d222b05e713e2bd2bf3d992568d0cc51a308ba679e123a1e3c8f222e2522b545a2db60fbc07869044c53b9449e
6
+ metadata.gz: f26d5cdd70cd05d93fc0cc596302a72089c1718fd5b58084b5a219333ac6b0ba034d09c7a0e57840fa790f4198c7b8ba24f8dfdaa0d0b85a5f7404246b922b07
7
+ data.tar.gz: 22e6d9304af0c182f4bd1bf7d4b34a9bc8d5435b505100bebe9519cdac2f3d29ba47db3fe7de48179cc88c191cac3da531de4d3b6f506c2275dc52f45b832444
data/CHANGELOG.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  ## master (unreleased)
4
4
 
5
+ - Add new TPS (tests per second) profiler. ([@palkan][])
6
+
5
7
  - FactoryDefault: add Fabrication support. ([@palkan][])
6
8
 
7
9
  - Drop support for **Ruby <2.7** and **Rails <6**.
@@ -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
- module RunnerExt
7
- refine TestProf::FactoryBot::FactoryRunner do
8
- attr_reader :name, :traits, :overrides
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
- using RunnerExt
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?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TestProf
4
- VERSION = "1.4.0.rc.2"
4
+ VERSION = "1.4.0.rc.3"
5
5
  end
data/lib/test_prof.rb CHANGED
@@ -12,5 +12,6 @@ require "test_prof/factory_prof"
12
12
  require "test_prof/memory_prof"
13
13
  require "test_prof/rspec_stamp"
14
14
  require "test_prof/tag_prof"
15
+ require "test_prof/tps_prof"
15
16
  require "test_prof/rspec_dissect" if TestProf.rspec?
16
17
  require "test_prof/factory_all_stub"
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.2
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-23 00:00:00.000000000 Z
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