crystalball 0.6.0 → 0.7.0

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
- SHA1:
3
- metadata.gz: 7640f5ca30ab5c0d596327158afebeafe350985f
4
- data.tar.gz: 2e517c5f0ddbd4b2eab12bcb7d691de92ac50ad8
2
+ SHA256:
3
+ metadata.gz: 51dd1b54ddce6da0c48bf4e7c0af2618179f882523e31c3b1c670b17638c6c7f
4
+ data.tar.gz: b82ae8f52e5000a846c8798e4c88905a1f62d0a1aed6ff81f9483d68a91d2581
5
5
  SHA512:
6
- metadata.gz: ae358c9b67c5d9b6e2d5f045eac7b02ffb7ecb9e6297358a8e91c75f0af925402f4a5c8eba201d3dbf962ca0103ac0c48278f48c34f2558bb16b82e63ce3fa8c
7
- data.tar.gz: de3db6bdda14d438b8a26a0981e91231df8c05339256009499b11bee01218d3d1456500d302d92118ce10faab2e7f959e5805db15b2dba46a6b301166ffcdd58
6
+ metadata.gz: 575147f129b34cf224ecf749eb85da0fe36944caa7b2ce9ef60bf606cdb3449f6f38866dfd0d1ba5b1d786f25167885af5700d940aa451e4224a5eb666801462
7
+ data.tar.gz: fb0d841b9af7eb7d6c0889520f1297ebed58786e2729580ffcdc5d152c7f1ad6bdc1988a7cb8c45900a05c5ca151e46a12823d17d92f10ed8520781c4114cd15
@@ -20,3 +20,5 @@ Style/MethodMissingSuper:
20
20
  Enabled: false
21
21
  Lint/AmbiguousBlockAssociation:
22
22
  Enabled: false
23
+ Style/DoubleNegation:
24
+ Enabled: false
@@ -1,5 +1,7 @@
1
1
  ## master (not released yet)
2
2
 
3
+ - Map storing structure reworked. Map size should be times smaller.
4
+
3
5
  ## Version 0.6.0
4
6
 
5
7
  - Add ModifiedSupportSpecs predictor
@@ -36,7 +36,6 @@ Gem::Specification.new do |spec|
36
36
 
37
37
  spec.add_development_dependency 'actionview'
38
38
  spec.add_development_dependency 'activerecord'
39
- spec.add_development_dependency "bundler", "~> 1.14"
40
39
  spec.add_development_dependency 'factory_bot'
41
40
  spec.add_development_dependency 'i18n'
42
41
  spec.add_development_dependency 'parser'
@@ -47,6 +46,6 @@ Gem::Specification.new do |spec|
47
46
  spec.add_development_dependency 'rubocop', ">= 0.56"
48
47
  spec.add_development_dependency 'rubocop-rspec'
49
48
  spec.add_development_dependency 'simplecov'
50
- spec.add_development_dependency 'sqlite3'
49
+ spec.add_development_dependency 'sqlite3', "~> 1.3.13"
51
50
  spec.add_development_dependency 'yard'
52
51
  end
@@ -11,7 +11,7 @@ Please check our [installation instructions](https://github.com/toptal/crystalba
11
11
 
12
12
  1. Start MapGenerator in your `spec_helper` before you loaded any file of your app. E.g.
13
13
 
14
- if ENV['CRYSTALBALL'] == 'true' do
14
+ if ENV['CRYSTALBALL'] == 'true'
15
15
  Crystalball::MapGenerator.start! do |config|
16
16
  config.register Crystalball::MapGenerator::CoverageStrategy.new
17
17
  end
@@ -135,6 +135,16 @@ Check out the [implementation](https://github.com/toptal/crystalball/tree/master
135
135
 
136
136
  Keep in mind that all the strategies configured for the map generator will run for each example of your test suite, so it may slow down the generation process considerably.
137
137
 
138
+ ### Debugging
139
+
140
+ By default MapGenerator generates compact map. In case you need plain and easily readable map add to your config:
141
+ ```ruby
142
+ Crystalball::MapGenerator.start! do |config|
143
+ #...
144
+ config.compact_map = false
145
+ end
146
+ ```
147
+
138
148
  ## TablesMapGenerator
139
149
 
140
150
  TablesMapGenerator is a separate map generator for Rails applications. It collects information about tables-to-models mapping and stores it in a file. The file is used by `Crystalball::Rails::Predictor::ModifiedSchema`.
@@ -147,3 +157,5 @@ Crystalball::TablesMapGenerator.start! do |config|
147
157
  config.map_storage_path = 'my_custom_tables_map_name.yml'
148
158
  end
149
159
  ```
160
+
161
+
@@ -19,6 +19,7 @@ require 'crystalball/map_generator/coverage_strategy'
19
19
  require 'crystalball/map_generator/allocated_objects_strategy'
20
20
  require 'crystalball/map_generator/described_class_strategy'
21
21
  require 'crystalball/map_storage/yaml_storage'
22
+ require 'crystalball/map_compactor'
22
23
  require 'crystalball/version'
23
24
 
24
25
  # Main module for the library
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ostruct'
4
+
5
+ require 'crystalball/example_group_map'
6
+ require 'crystalball/execution_map'
7
+ require 'crystalball/map_compactor/example_groups_data_compactor'
8
+
9
+ module Crystalball
10
+ # a module for compacting execution map by moving out repeated used files to upper contexts records.
11
+ module MapCompactor
12
+ class << self
13
+ # @param [Crystalball::ExecutionMap] map execution map to be compacted
14
+ # @return [Crystalball::ExecutionMap] compact map
15
+ def compact_map!(map)
16
+ new_map = Crystalball::ExecutionMap.new(metadata: map.metadata.to_h)
17
+
18
+ compact_examples!(map.example_groups).each do |context, used_files|
19
+ new_map << ExampleGroupMap.new(OpenStruct.new(id: context, file_path: example_filename(context)), used_files)
20
+ end
21
+
22
+ new_map
23
+ end
24
+
25
+ def compact_examples!(example_groups)
26
+ result = {}
27
+ example_groups.group_by { |k, _v| example_filename(k) }.each do |filename, examples|
28
+ compact_data = ExampleGroupsDataCompactor.compact!(examples.to_h)
29
+
30
+ compact_data.each do |context_address, used_files|
31
+ result["#{filename}[#{context_address}]"] = used_files unless used_files.empty?
32
+ end
33
+ end
34
+ result
35
+ end
36
+
37
+ private
38
+
39
+ def example_filename(example_id)
40
+ example_id.split('[').first
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Crystalball
4
+ module MapCompactor
5
+ # Class representing RSpec context data
6
+ class ExampleContext
7
+ attr_reader :address
8
+
9
+ def initialize(address)
10
+ @address = address
11
+ end
12
+
13
+ def parent
14
+ @parent ||= begin
15
+ parent_uid = address.split(':')[0..-2].join(':')
16
+ parent_uid.empty? ? nil : self.class.new(parent_uid)
17
+ end
18
+ end
19
+
20
+ def include?(example_id)
21
+ example_id =~ /\[#{address}[\:\]]/
22
+ end
23
+
24
+ def depth
25
+ @depth ||= address.split(':').size
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'crystalball/map_compactor/example_context'
4
+
5
+ module Crystalball
6
+ module MapCompactor
7
+ # Class representing example groups data compacting logic for a single file
8
+ class ExampleGroupsDataCompactor
9
+ # @param [Hash] plain_data a hash of examples and used files
10
+ def self.compact!(plain_data)
11
+ new(plain_data).compact!
12
+ end
13
+
14
+ def compact!
15
+ contexts = extract_contexts(plain_data.keys).sort_by(&:depth)
16
+
17
+ contexts.each do |context|
18
+ compact_data[context.address] = compact_context!(context)
19
+ end
20
+ compact_data
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :compact_data, :plain_data
26
+
27
+ def initialize(plain_data)
28
+ @plain_data = plain_data
29
+ @compact_data = {}
30
+ end
31
+
32
+ def compact_context!(context) # rubocop:disable Metrics/MethodLength
33
+ result = nil
34
+ plain_data.each do |example_uid, used_files|
35
+ next unless context.include?(example_uid)
36
+
37
+ if result.nil?
38
+ result = used_files
39
+ result -= deep_used_files(context.parent) if context.parent
40
+ else
41
+ result &= used_files
42
+ end
43
+ end
44
+ result
45
+ end
46
+
47
+ def deep_used_files(context)
48
+ result = compact_data[context.address]
49
+ result += deep_used_files(context.parent) if context.parent
50
+ result
51
+ end
52
+
53
+ def extract_contexts(example_uids)
54
+ result = []
55
+ example_uids.each do |example_uid|
56
+ context_numbers = /\[(.*)\]/.match(example_uid)[1].split(':')
57
+ until context_numbers.empty?
58
+ result << ExampleContext.new(context_numbers.join(':'))
59
+ context_numbers.pop
60
+ end
61
+ end
62
+ result.compact.uniq(&:address)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -52,7 +52,11 @@ module Crystalball
52
52
  return unless started
53
53
 
54
54
  strategies.each(&:before_finalize)
55
- map_storage.dump(map.example_groups) if map.size.positive?
55
+
56
+ return unless map.size.positive?
57
+
58
+ example_groups = (configuration.compact_map? ? MapCompactor.compact_map!(map) : map).example_groups
59
+ map_storage.dump(example_groups)
56
60
  end
57
61
 
58
62
  def map
@@ -70,6 +74,7 @@ module Crystalball
70
74
  end
71
75
 
72
76
  def check_dump_threshold
77
+ return if configuration.compact_map
73
78
  return unless dump_threshold.positive? && map.size >= dump_threshold
74
79
 
75
80
  map_storage.dump(map.example_groups)
@@ -9,13 +9,17 @@ module Crystalball
9
9
  class Configuration
10
10
  attr_writer :map_storage
11
11
  attr_writer :map_class
12
- attr_accessor :commit
13
- attr_accessor :version
12
+ attr_accessor :commit, :version, :compact_map
14
13
 
15
14
  attr_reader :strategies
16
15
 
17
16
  def initialize
18
17
  @strategies = StrategiesCollection.new
18
+ @compact_map = true
19
+ end
20
+
21
+ def compact_map?
22
+ !!@compact_map
19
23
  end
20
24
 
21
25
  def map_class
@@ -21,7 +21,7 @@ module Crystalball
21
21
 
22
22
  guard_metadata_consistency(meta)
23
23
 
24
- Object.const_get(meta.first[:type]).new(metadata: meta.first, example_groups: example_groups.inject(&:merge!))
24
+ Object.const_get(meta.first[:type]).new(metadata: meta.first, example_groups: example_groups.compact.inject(&:merge!))
25
25
  end
26
26
 
27
27
  private
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'crystalball/source_diff/file_diff'
4
4
  require 'crystalball/source_diff/formatting_checker'
5
+ require 'forwardable'
5
6
 
6
7
  module Crystalball
7
8
  # Wrapper class representing Git source diff for given repo
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Crystalball
4
- VERSION = '0.6.0'
4
+ VERSION = '0.7.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crystalball
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Shutsin
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2018-10-04 00:00:00.000000000 Z
13
+ date: 2019-07-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: git
@@ -54,20 +54,6 @@ dependencies:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
- - !ruby/object:Gem::Dependency
58
- name: bundler
59
- requirement: !ruby/object:Gem::Requirement
60
- requirements:
61
- - - "~>"
62
- - !ruby/object:Gem::Version
63
- version: '1.14'
64
- type: :development
65
- prerelease: false
66
- version_requirements: !ruby/object:Gem::Requirement
67
- requirements:
68
- - - "~>"
69
- - !ruby/object:Gem::Version
70
- version: '1.14'
71
57
  - !ruby/object:Gem::Dependency
72
58
  name: factory_bot
73
59
  requirement: !ruby/object:Gem::Requirement
@@ -212,16 +198,16 @@ dependencies:
212
198
  name: sqlite3
213
199
  requirement: !ruby/object:Gem::Requirement
214
200
  requirements:
215
- - - ">="
201
+ - - "~>"
216
202
  - !ruby/object:Gem::Version
217
- version: '0'
203
+ version: 1.3.13
218
204
  type: :development
219
205
  prerelease: false
220
206
  version_requirements: !ruby/object:Gem::Requirement
221
207
  requirements:
222
- - - ">="
208
+ - - "~>"
223
209
  - !ruby/object:Gem::Version
224
- version: '0'
210
+ version: 1.3.13
225
211
  - !ruby/object:Gem::Dependency
226
212
  name: yard
227
213
  requirement: !ruby/object:Gem::Requirement
@@ -275,6 +261,9 @@ files:
275
261
  - lib/crystalball/factory_bot.rb
276
262
  - lib/crystalball/git_repo.rb
277
263
  - lib/crystalball/logging.rb
264
+ - lib/crystalball/map_compactor.rb
265
+ - lib/crystalball/map_compactor/example_context.rb
266
+ - lib/crystalball/map_compactor/example_groups_data_compactor.rb
278
267
  - lib/crystalball/map_generator.rb
279
268
  - lib/crystalball/map_generator/allocated_objects_strategy.rb
280
269
  - lib/crystalball/map_generator/allocated_objects_strategy/object_tracker.rb
@@ -350,8 +339,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
350
339
  - !ruby/object:Gem::Version
351
340
  version: '0'
352
341
  requirements: []
353
- rubyforge_project:
354
- rubygems_version: 2.6.14.1
342
+ rubygems_version: 3.0.3
355
343
  signing_key:
356
344
  specification_version: 4
357
345
  summary: A library for RSpec regression test selection