gitlab-crystalball 0.7.2 → 0.8.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3059723052c6c3bfe9f58ee458b2ab15ef18aaf4227c4ec3a5eeefd53c8630e1
4
- data.tar.gz: 892c339d1bf8bbf599dba57b6bbf45b1f0ab8dfb1c41b2df1c279c22a6df8d24
3
+ metadata.gz: 4ecaca1010fa8832b924a6acd3e9163175ffa144a13b8d298ee35d5b8baaf546
4
+ data.tar.gz: 84af3bed1b01cdd235c881e948c033da9a630102ad6133ac3b181df24dc52545
5
5
  SHA512:
6
- metadata.gz: c9e81eef06568c4b5dd3c757d8507427d448cf48a7f050704c877abc23f5f7711f769e16f3ef75f08aa4797dd4c0fb2120dceb6ca1ce7add83cf7b73f6fcab27
7
- data.tar.gz: 71106979d5350594e4344d3404e9bc1bcc282b81c5180ca8e0e51ab73dbb7c760ab35402444e71fcb95cea6c258bf6dab756d6adfecc363b87c4c8ac6bf362a3
6
+ metadata.gz: e9fac346de4eb92f888b3fe3cad20c5618058f329c76b7c3b08e61b2ac0ac913f2e52f650c568b017cb38280ee4dd62f1ae68c3155eacc31f1efbfdb33e9582c
7
+ data.tar.gz: d9b2d7d86a787e8bed3c4ade3561d58593f8f146a477babfab4ed63a638b9c2d52059b44777dc250f1eec082f360f285effa1c7054f7569175284b1c78ed549a
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Crystalball
2
2
 
3
- ![Build Status](https://gitlab.com/acunskis/crystalball/badges/main/pipeline.svg)
4
- ![Test Coverage](https://gitlab.com/acunskis/crystalball/badges/main/coverage.svg?job=rspec)
3
+ ![Build Status](https://gitlab.com/gitlab-org/ruby/gems/crystalball/badges/main/pipeline.svg)
4
+ ![Test Coverage](https://gitlab.com/gitlab-org/ruby/gems/crystalball/badges/main/coverage.svg?job=rspec%20spec)
5
5
 
6
6
  Crystalball is a Ruby library which implements [Regression Test Selection mechanism](https://tenderlovemaking.com/2015/02/13/predicting-test-failues.html) originally published by Aaron Patterson.
7
7
  Its main purpose is to select a minimal subset of your test suite which should be run to ensure your changes didn't break anything.
@@ -30,11 +30,11 @@ Or install it yourself as:
30
30
 
31
31
  ## Usage
32
32
 
33
- Please see our [official documentation](https://gitlab.com/acunskis/crystalball/-/blob/main/docs/index.md).
33
+ Please see our [official documentation](https://gitlab.com/gitlab-org/ruby/gems/crystalball/-/blob/main/docs/index.md).
34
34
 
35
35
  ### Versioning
36
36
 
37
- We use [semantic versioning](https://semver.org/) for our [releases](https://gitlab.com/acunskis/crystalball/-/releases).
37
+ We use [semantic versioning](https://semver.org/) for our [releases](https://gitlab.com/gitlab-org/ruby/gems/crystalball/-/releases).
38
38
 
39
39
  ## Development
40
40
 
@@ -8,6 +8,7 @@ module Crystalball
8
8
  # Class for detecting code execution path based on coverage information diff
9
9
  class ExecutionDetector
10
10
  include ::Crystalball::MapGenerator::Helpers::PathFilter
11
+
11
12
  # Detects files affected during example execution. Transforms absolute paths to relative.
12
13
  # Exclude paths outside of repository
13
14
  #
@@ -15,7 +16,15 @@ module Crystalball
15
16
  # @param[Array<String>] list of files affected after example execution
16
17
  # @return [Array<String>]
17
18
  def detect(before, after)
18
- filter after.reject { |file_name, after_coverage| before[file_name] == after_coverage }.keys
19
+ after.filter_map do |file, coverage|
20
+ before_cov = before[file]&.fetch(:lines, [])
21
+ next if before_cov == coverage[:lines]
22
+
23
+ path = valid_path(file)
24
+ next unless path
25
+
26
+ path
27
+ end
19
28
  end
20
29
  end
21
30
  end
@@ -12,12 +12,12 @@ module Crystalball
12
12
 
13
13
  attr_reader :execution_detector
14
14
 
15
- def initialize(execution_detector = ExecutionDetector.new)
15
+ def initialize(execution_detector: ExecutionDetector.new)
16
16
  @execution_detector = execution_detector
17
17
  end
18
18
 
19
19
  def after_register
20
- Coverage.start unless Coverage.running?
20
+ Coverage.start(lines: true) unless Coverage.running?
21
21
  end
22
22
 
23
23
  # Adds to the example_map's used files the ones the ones in which
@@ -5,19 +5,38 @@ module Crystalball
5
5
  module Helpers
6
6
  # Helper module to filter file paths
7
7
  module PathFilter
8
- attr_reader :root_path
8
+ attr_reader :root_path, :exclude_prefixes
9
9
 
10
10
  # @param [String] root_path - absolute path to root folder of repository
11
- def initialize(root_path = Dir.pwd)
11
+ # @param [Array] exclude_prefixes - list of prefixes to filter out from paths
12
+ def initialize(root_path = Dir.pwd, exclude_prefixes: [])
12
13
  @root_path = root_path
14
+ @exclude_prefixes = exclude_prefixes
13
15
  end
14
16
 
15
17
  # @param [Array<String>] paths
16
- # @return relatve paths inside root_path only
18
+ # @return relative paths inside root_path only
17
19
  def filter(paths)
18
- paths
19
- .select { |file_name| file_name.start_with?(root_path) }
20
- .map { |file_name| file_name.sub("#{root_path}/", "") }
20
+ paths.filter_map do |path|
21
+ next unless path.start_with?(root_path)
22
+
23
+ valid_path(path)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ # Return relative path if it is a valid path
30
+ #
31
+ # @param path [String]
32
+ # @return [<String, nil>]
33
+ def valid_path(path)
34
+ return unless path.start_with?(root_path)
35
+
36
+ relative_path = path.sub("#{root_path}/", "")
37
+ return if exclude_prefixes&.any? { |prefix| relative_path.start_with?(prefix) }
38
+
39
+ relative_path
21
40
  end
22
41
  end
23
42
  end
@@ -13,11 +13,12 @@ module Crystalball
13
13
  attr_reader :definition_tracer, :hierarchy_fetcher
14
14
 
15
15
  def initialize(
16
- root_path:,
16
+ root_path: Dir.pwd,
17
17
  definition_tracer: DefinitionTracer.new(root_path),
18
- hierarchy_fetcher: HierarchyFetcher.new
18
+ hierarchy_fetcher: HierarchyFetcher.new,
19
+ exclude_prefixes: []
19
20
  )
20
- super(root_path)
21
+ super(root_path, exclude_prefixes: exclude_prefixes)
21
22
 
22
23
  @definition_tracer = definition_tracer
23
24
  @hierarchy_fetcher = hierarchy_fetcher
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "coverage"
4
+ require "crystalball/map_generator/base_strategy"
5
+
6
+ require_relative "helpers/path_filter"
7
+
8
+ module Crystalball
9
+ class MapGenerator
10
+ # Map generator strategy based on harvesting Coverage information during example execution
11
+ class OneshotCoverageStrategy
12
+ include BaseStrategy
13
+ include Helpers::PathFilter
14
+
15
+ def after_register
16
+ raise "Coverage must not be started for oneshot_line strategy" if Coverage.running?
17
+ end
18
+
19
+ # Adds to the example_map's used files the ones the ones in which
20
+ # the coverage has changed after the tests runs.
21
+ # @param [Crystalball::ExampleGroupMap] example_map - object holding example metadata and used files
22
+ # @param [RSpec::Core::Example] example - a RSpec example
23
+ def call(example_map, example)
24
+ Coverage.start(oneshot_lines: true)
25
+ yield example_map, example
26
+ paths = Coverage.result.keys
27
+ example_map.push(*filter(paths))
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Crystalball
4
- VERSION = "0.7.2"
4
+ VERSION = "0.8.1"
5
5
  end
data/lib/crystalball.rb CHANGED
@@ -16,6 +16,7 @@ require "crystalball/execution_map"
16
16
  require "crystalball/map_generator"
17
17
  require "crystalball/map_generator/configuration"
18
18
  require "crystalball/map_generator/coverage_strategy"
19
+ require "crystalball/map_generator/oneshot_coverage_strategy"
19
20
  require "crystalball/map_generator/allocated_objects_strategy"
20
21
  require "crystalball/map_generator/described_class_strategy"
21
22
  require "crystalball/map_storage/yaml_storage"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-crystalball
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Developer Experience Team
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-05-08 00:00:00.000000000 Z
10
+ date: 2025-05-13 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: git
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - "<"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '4'
26
+ - !ruby/object:Gem::Dependency
27
+ name: ostruct
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '1'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "<"
38
+ - !ruby/object:Gem::Version
39
+ version: '1'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: actionview
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -247,6 +261,7 @@ files:
247
261
  - lib/crystalball/map_generator/object_sources_detector.rb
248
262
  - lib/crystalball/map_generator/object_sources_detector/definition_tracer.rb
249
263
  - lib/crystalball/map_generator/object_sources_detector/hierarchy_fetcher.rb
264
+ - lib/crystalball/map_generator/oneshot_coverage_strategy.rb
250
265
  - lib/crystalball/map_generator/parser_strategy.rb
251
266
  - lib/crystalball/map_generator/parser_strategy/processor.rb
252
267
  - lib/crystalball/map_generator/strategies_collection.rb
@@ -285,14 +300,14 @@ files:
285
300
  - lib/crystalball/source_diff/file_diff.rb
286
301
  - lib/crystalball/source_diff/formatting_checker.rb
287
302
  - lib/crystalball/version.rb
288
- homepage: https://gitlab.com/acunskis/crystalball
303
+ homepage: https://gitlab.com/gitlab-org/ruby/gems/crystalball
289
304
  licenses: []
290
305
  metadata:
291
- bug_tracker_uri: https://gitlab.com/acunskis/crystalball/-/issues
292
- changelog_uri: https://gitlab.com/acunskis/crystalball/-/releases
293
- documentation_uri: https://gitlab.com/acunskis/crystalball/-/blob/main/docs/index.md
294
- source_code_uri: https://gitlab.com/acunskis/crystalball/-/tree/main
295
- wiki_uri: https://gitlab.com/acunskis/crystalball/-/wikis/home
306
+ bug_tracker_uri: https://gitlab.com/gitlab-org/ruby/gems/crystalball/-/issues
307
+ changelog_uri: https://gitlab.com/gitlab-org/ruby/gems/crystalball/-/releases
308
+ documentation_uri: https://gitlab.com/gitlab-org/ruby/gems/crystalball/-/blob/main/docs/index.md
309
+ source_code_uri: https://gitlab.com/gitlab-org/ruby/gems/crystalball/-/tree/main
310
+ wiki_uri: https://gitlab.com/gitlab-org/ruby/gems/crystalball/-/wikis/home
296
311
  rubygems_mfa_required: 'false'
297
312
  rdoc_options: []
298
313
  require_paths: