scientist 1.6.3 → 1.6.5

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: 53663e0ed4b522336c69b73073aa144a4b6c8178e3fcd716c0e4519a66e308ba
4
- data.tar.gz: b60d0c55dce9e1e9a23eb7e6ce4c445bf01340dcfd459d50716d7cd85e405b93
3
+ metadata.gz: 426765524d161804bb79075cb364ff3101c630da521af30c6f7f79e7e65244a8
4
+ data.tar.gz: a25d075270905c82d63eff97ae773205c3a1b7f3ddb1fc766ee822dd5ee1edfd
5
5
  SHA512:
6
- metadata.gz: 6e1baf64882c857abdd3fd02b77785a783a8694854358c78a9da3be213b42ac88e36805ebf7f10f0d87fb14d7808302e1afffd2793c5ffc21addec5326e5f969
7
- data.tar.gz: e5a65140ca8704c7443f88404cfb9e971f4a2925d756eed18d7482be74aab3243315fda727dfe8fed13d0732d76ca442a12cb7af200ca6ae3e4de4b0f1bab1a2
6
+ metadata.gz: c48b5826e463c8c1d59c147509f4ced8e371b022da15da5f8d63b038d2d9ef42945951fbf1901924a8570f24de9c95f4c1b33ca430ed47ac2e243383bde4652c
7
+ data.tar.gz: 19af496de9ceb3f2d2bdb933656d60830941489ab0702c4753247c606886184a5d1c8c7e25ceda26bc2f8ed5cdf6ec3ee833a74c44ec081a814584e0a5e8b677
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -0,0 +1,34 @@
1
+ name: CI
2
+ on: [push, pull_request]
3
+ permissions:
4
+ actions: none
5
+ checks: write
6
+ contents: read
7
+ deployments: none
8
+ issues: none
9
+ packages: none
10
+ pull-requests: none
11
+ repository-projects: none
12
+ security-events: none
13
+ statuses: write
14
+ jobs:
15
+ build:
16
+ name: ruby-${{ matrix.ruby_version }}
17
+ runs-on: ubuntu-latest
18
+ strategy:
19
+ fail-fast: false
20
+ matrix:
21
+ ruby_version:
22
+ - "2.6"
23
+ - "2.7"
24
+ - "3.0"
25
+ - "3.1"
26
+ - "3.2"
27
+ - "3.3"
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: ${{ matrix.ruby_version }}
33
+ bundler-cache: true
34
+ - run: bundle exec rake
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Scientist!
2
2
 
3
- A Ruby library for carefully refactoring critical paths. [![Build Status](https://travis-ci.org/github/scientist.svg?branch=master)](https://travis-ci.org/github/scientist) [![Coverage Status](https://coveralls.io/repos/github/github/scientist/badge.svg?branch=master)](https://coveralls.io/github/github/scientist?branch=master)
3
+ A Ruby library for carefully refactoring critical paths. [![Build Status](https://github.com/github/scientist/actions/workflows/ci.yml/badge.svg)](https://github.com/github/scientist/actions/workflows/ci.yml)
4
4
 
5
5
  ## How do I science?
6
6
 
@@ -12,7 +12,7 @@ require "scientist"
12
12
  class MyWidget
13
13
  def allows?(user)
14
14
  experiment = Scientist::Default.new "widget-permissions"
15
- experiment.use { model.check_user?(user).valid? } # old way
15
+ experiment.use { model.check_user(user).valid? } # old way
16
16
  experiment.try { user.can?(:read, model) } # new way
17
17
 
18
18
  experiment.run
@@ -24,7 +24,7 @@ Wrap a `use` block around the code's original behavior, and wrap `try` around th
24
24
 
25
25
  * It decides whether or not to run the `try` block,
26
26
  * Randomizes the order in which `use` and `try` blocks are run,
27
- * Measures the durations of all behaviors in seconds,
27
+ * Measures the wall time and cpu time of all behaviors in seconds,
28
28
  * Compares the result of `try` to the result of `use`,
29
29
  * Swallow and record exceptions raised in the `try` block when overriding `raised`, and
30
30
  * Publishes all this information.
@@ -109,7 +109,7 @@ class MyWidget
109
109
  end
110
110
  ```
111
111
 
112
- If either the control block or candidate block raises an error, Scientist compares the two observations' classes and messages using `==`. To override this behavior, use `compare_error` to define how to compare observed errors instead:
112
+ If either the control block or candidate block raises an error, Scientist compares the two observations' classes and messages using `==`. To override this behavior, use `compare_errors` to define how to compare observed errors instead:
113
113
 
114
114
  ```ruby
115
115
  class MyWidget
@@ -121,7 +121,7 @@ class MyWidget
121
121
  e.try { UserService.slug_from_login login } # returns String instance or ArgumentError
122
122
 
123
123
  compare_error_message_and_class = -> (control, candidate) do
124
- control.class == candidate.class &&
124
+ control.class == candidate.class &&
125
125
  control.message == candidate.message
126
126
  end
127
127
 
@@ -129,10 +129,10 @@ class MyWidget
129
129
  control.class == ArgumentError &&
130
130
  candidate.class == ArgumentError &&
131
131
  control.message.start_with?("Input has invalid characters") &&
132
- candidate.message.start_with?("Invalid characters in input")
132
+ candidate.message.start_with?("Invalid characters in input")
133
133
  end
134
134
 
135
- e.compare_error do |control, candidate|
135
+ e.compare_errors do |control, candidate|
136
136
  compare_error_message_and_class.call(control, candidate) ||
137
137
  compare_argument_errors.call(control, candidate)
138
138
  end
@@ -241,6 +241,19 @@ end
241
241
 
242
242
  Note that the `#clean` method will discard the previous cleaner block if you call it again. If for some reason you need to access the currently configured cleaner block, `Scientist::Experiment#cleaner` will return the block without further ado. _(This probably won't come up in normal usage, but comes in handy if you're writing, say, a custom experiment runner that provides default cleaners.)_
243
243
 
244
+ The `#clean` method will not be used for comparison of the results, so in the following example it is not possible to remove the `#compare` method without the experiment failing:
245
+
246
+ ```ruby
247
+ def user_ids
248
+ science "user_ids" do
249
+ e.use { [1,2,3] }
250
+ e.try { [1,3,2] }
251
+ e.clean { |value| value.sort }
252
+ e.compare { |a, b| a.sort == b.sort }
253
+ end
254
+ end
255
+ ```
256
+
244
257
  ### Ignoring mismatches
245
258
 
246
259
  During the early stages of an experiment, it's possible that some of your code will always generate a mismatch for reasons you know and understand but haven't yet fixed. Instead of these known cases always showing up as mismatches in your metrics or analysis, you can tell an experiment whether or not to ignore a mismatch using the `ignore` method. You may include more than one block if needed:
@@ -260,7 +273,7 @@ def admin?(user)
260
273
  end
261
274
  ```
262
275
 
263
- The ignore blocks are only called if the *values* don't match. Unless a `compare_error` comparator is defined, two cases are considered mismatches: a) one observation raising an exception and the other not, b) observations raising exceptions with different classes or messages.
276
+ The ignore blocks are only called if the *values* don't match. Unless a `compare_errors` comparator is defined, two cases are considered mismatches: a) one observation raising an exception and the other not, b) observations raising exceptions with different classes or messages.
264
277
 
265
278
  ### Enabling/disabling experiments
266
279
 
@@ -321,11 +334,18 @@ class MyExperiment
321
334
 
322
335
  def publish(result)
323
336
 
337
+ # Wall time
324
338
  # Store the timing for the control value,
325
339
  $statsd.timing "science.#{name}.control", result.control.duration
326
340
  # for the candidate (only the first, see "Breaking the rules" below,
327
341
  $statsd.timing "science.#{name}.candidate", result.candidates.first.duration
328
342
 
343
+ # CPU time
344
+ # Store the timing for the control value,
345
+ $statsd.timing "science.cpu.#{name}.control", result.control.cpu_time
346
+ # for the candidate (only the first, see "Breaking the rules" below,
347
+ $statsd.timing "science.cpu.#{name}.candidate", result.candidates.first.cpu_time
348
+
329
349
  # and counts for match/ignore/mismatch:
330
350
  if result.matched?
331
351
  $statsd.increment "science.#{name}.matched"
@@ -530,17 +550,22 @@ end
530
550
 
531
551
  #### Providing fake timing data
532
552
 
533
- If you're writing tests that depend on specific timing values, you can provide canned durations using the `fabricate_durations_for_testing_purposes` method, and Scientist will report these in `Scientist::Observation#duration` instead of the actual execution times.
553
+ If you're writing tests that depend on specific timing values, you can provide canned durations using the `fabricate_durations_for_testing_purposes` method, and Scientist will report these in `Scientist::Observation#duration` and `Scientist::Observation#cpu_time` instead of the actual execution times.
534
554
 
535
555
  ```ruby
536
556
  science "absolutely-nothing-suspicious-happening-here" do |e|
537
557
  e.use { ... } # "control"
538
558
  e.try { ... } # "candidate"
539
- e.fabricate_durations_for_testing_purposes( "control" => 1.0, "candidate" => 0.5 )
559
+ e.fabricate_durations_for_testing_purposes({
560
+ "control" => { "duration" => 1.0, "cpu_time" => 0.9 },
561
+ "candidate" => { "duration" => 0.5, "cpu_time" => 0.4 }
562
+ })
540
563
  end
541
564
  ```
542
565
 
543
- `fabricate_durations_for_testing_purposes` takes a Hash of duration values, keyed by behavior names. (By default, Scientist uses `"control"` and `"candidate"`, but if you override these as shown in [Trying more than one thing](#trying-more-than-one-thing) or [No control, just candidates](#no-control-just-candidates), use matching names here.) If a name is not provided, the actual execution time will be reported instead.
566
+ `fabricate_durations_for_testing_purposes` takes a Hash of duration & cpu_time values, keyed by behavior names. (By default, Scientist uses `"control"` and `"candidate"`, but if you override these as shown in [Trying more than one thing](#trying-more-than-one-thing) or [No control, just candidates](#no-control-just-candidates), use matching names here.) If a name is not provided, the actual execution time will be reported instead.
567
+
568
+ We should mention these durations will be used both for the `duration` field and the `cpu_time` field.
544
569
 
545
570
  _Like `Scientist::Experiment#cleaner`, this probably won't come up in normal usage. It's here to make it easier to test code that extends Scientist._
546
571
 
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "rake/testtask"
2
+
3
+ task default: "test"
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.test_files = FileList['test/test_helper.rb', 'test/**/*_test.rb']
7
+ end
data/doc/changelog.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # Changes
2
2
 
3
+ ## v1.6.5 (16 December 2024)
4
+
5
+ - New: measure CPU time alongside wall time for experiments #275
6
+
7
+ ## v1.6.4 (5 April 2023)
8
+
9
+ - New: GitHub Actions for CI #171
10
+ - New: add ruby 3.1 support #175
11
+ - Fix: `compare_errors` in docs #178
12
+ - Fix: remove outdated travis configs #179
13
+ - Fix: typos #191
14
+ - New: add support for `after_run` blocks #211
15
+
16
+ ## v1.6.3 (9 December 2021)
17
+
18
+ - Fix: improve marshaling implementation #169
19
+
20
+ ## v1.6.2 (4 November 2021)
21
+
22
+ - New: make `MismatchError` marshalable #168
23
+
24
+ ## v1.6.1 (22 October 2021)
25
+
26
+ - Fix: moving supported ruby versions from <=2.3 to >=2.6 #150
27
+ - Fix: update docs to explain timeout handling #159
28
+ - New: add support for comparing errors #77
29
+
30
+ ## v1.6.0 (8 March 2021)
31
+
32
+ - Fix: clarify unit for observations #124
33
+ - New: enable support for truffleruby #143
34
+ - Fix: don't default experiment when included in a module #144
35
+
36
+ ## v1.5.0 (8 September 2020)
37
+
38
+ - Fix: clearer explanation of exception handling #110
39
+ - Fix: remove unused attribute from `Scientist::Observation` #119
40
+ - New: Added internal extension point for generating experinet results #121
41
+ - New: Add `Scientist::Experiment.register` helper #104
42
+
43
+ ## v1.4.0 (20 September 2019)
44
+
45
+ - New: Make `MismatchError` a base `Exception` #107
46
+
3
47
  ## v1.3.0 (2 April 2019)
4
48
 
5
49
  - New: Drop support for ruby <2.3
@@ -87,6 +87,16 @@ module Scientist::Experiment
87
87
  @_scientist_before_run = block
88
88
  end
89
89
 
90
+ # Define a block of code to run after an experiment completes, if the experiment
91
+ # is enabled.
92
+ #
93
+ # The block takes one argument, the Scientist::Result containing experiment results.
94
+ #
95
+ # Returns the configured block.
96
+ def after_run(&block)
97
+ @_scientist_after_run = block
98
+ end
99
+
90
100
  # A Hash of behavior blocks, keyed by String name. Register behavior blocks
91
101
  # with the `try` and `use` methods.
92
102
  def behaviors
@@ -230,6 +240,10 @@ module Scientist::Experiment
230
240
 
231
241
  result = generate_result(name)
232
242
 
243
+ if @_scientist_after_run
244
+ @_scientist_after_run.call(result)
245
+ end
246
+
233
247
  begin
234
248
  publish(result)
235
249
  rescue StandardError => ex
@@ -331,7 +345,7 @@ module Scientist::Experiment
331
345
  [@name, @result, @raise_on_mismatches]
332
346
  end
333
347
 
334
- def marshal_load
348
+ def marshal_load(array)
335
349
  @name, @result, @raise_on_mismatches = array
336
350
  end
337
351
  end
@@ -20,19 +20,32 @@ class Scientist::Observation
20
20
  # The Float seconds elapsed.
21
21
  attr_reader :duration
22
22
 
23
+ # The Float CPU time elapsed, in seconds
24
+ attr_reader :cpu_time
25
+
23
26
  def initialize(name, experiment, fabricated_duration: nil, &block)
24
27
  @name = name
25
28
  @experiment = experiment
26
29
 
27
- starting = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second) unless fabricated_duration
30
+ start_wall_time, start_cpu_time = capture_times unless fabricated_duration
31
+
28
32
  begin
29
33
  @value = block.call
30
34
  rescue *RESCUES => e
31
35
  @exception = e
32
36
  end
33
37
 
34
- @duration = fabricated_duration ||
35
- Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second) - starting
38
+ if fabricated_duration.is_a?(Hash)
39
+ @duration = fabricated_duration["duration"]
40
+ @cpu_time = fabricated_duration["cpu_time"]
41
+ elsif fabricated_duration
42
+ @duration = fabricated_duration
43
+ @cpu_time = 0.0 # setting a default value
44
+ else
45
+ end_wall_time, end_cpu_time = capture_times
46
+ @duration = end_wall_time - start_wall_time
47
+ @cpu_time = end_cpu_time - start_cpu_time
48
+ end
36
49
 
37
50
  freeze
38
51
  end
@@ -58,7 +71,7 @@ class Scientist::Observation
58
71
  # * The values of the observation are equal (using `==`)
59
72
  # * The values of the observations are equal according to a comparison
60
73
  # proc, if given
61
- # * The exceptions raised by the obeservations are equal according to the
74
+ # * The exceptions raised by the observations are equal according to the
62
75
  # error comparison proc, if given.
63
76
  # * Both observations raised an exception with the same class and message.
64
77
  #
@@ -89,4 +102,13 @@ class Scientist::Observation
89
102
  def raised?
90
103
  !exception.nil?
91
104
  end
105
+
106
+ private
107
+
108
+ def capture_times
109
+ [
110
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_second),
111
+ Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID, :float_second)
112
+ ]
113
+ end
92
114
  end
@@ -1,3 +1,3 @@
1
1
  module Scientist
2
- VERSION = "1.6.3"
2
+ VERSION = '1.6.5'
3
3
  end
data/scientist.gemspec CHANGED
@@ -18,5 +18,5 @@ Gem::Specification.new do |gem|
18
18
  gem.require_paths = ["lib"]
19
19
 
20
20
  gem.add_development_dependency "minitest", "~> 5.8"
21
- gem.add_development_dependency "coveralls", "~> 0.8"
21
+ gem.add_development_dependency "rake"
22
22
  end
data/script/test CHANGED
@@ -4,9 +4,4 @@
4
4
  set -e
5
5
 
6
6
  cd $(dirname "$0")/..
7
- script/bootstrap && bundle exec ruby -I lib \
8
- -e 'require "bundler/setup"' \
9
- -e 'require "coveralls"; Coveralls.wear!{ add_filter ".bundle" }' \
10
- -e 'require "minitest/autorun"' \
11
- -e 'require "scientist"' \
12
- -e '(ARGV.empty? ? Dir["test/**/*_test.rb"] : ARGV).each { |f| load f }' -- "$@"
7
+ script/bootstrap && bundle exec rake test
@@ -512,6 +512,10 @@ describe Scientist::Experiment do
512
512
  assert_kind_of(String, Marshal.dump(mismatch))
513
513
  end
514
514
 
515
+ it "can be marshal loaded" do
516
+ assert_kind_of(Fake, Marshal.load(Marshal.dump(@ex)))
517
+ end
518
+
515
519
  describe "#raise_on_mismatches?" do
516
520
  it "raises when there is a mismatch if the experiment instance's raise on mismatches is enabled" do
517
521
  Fake.raise_on_mismatches = false
@@ -635,8 +639,39 @@ candidate:
635
639
  end
636
640
  end
637
641
 
642
+ describe "after run block" do
643
+ it "runs when an experiment is enabled" do
644
+ control_ok = candidate_ok = false
645
+ after_result = nil
646
+ @ex.after_run { |result| after_result = result }
647
+ @ex.use { control_ok = after_result.nil? }
648
+ @ex.try { candidate_ok = after_result.nil? }
649
+
650
+ @ex.run
651
+
652
+ assert after_result, "after_run should have run"
653
+ assert after_result.matched?, "after_run should be called with the result"
654
+ assert control_ok, "control should have run before after_run"
655
+ assert candidate_ok, "candidate should have run before after_run"
656
+ end
657
+
658
+ it "does not run when an experiment is disabled" do
659
+ after_result = nil
660
+
661
+ def @ex.enabled?
662
+ false
663
+ end
664
+ @ex.after_run { |result| after_result = result }
665
+ @ex.use { "value" }
666
+ @ex.try { "value" }
667
+ @ex.run
668
+
669
+ refute after_result, "after_run should not have run"
670
+ end
671
+ end
672
+
638
673
  describe "testing hooks for extending code" do
639
- it "allows a user to provide fabricated durations for testing purposes" do
674
+ it "allows a user to provide fabricated durations for testing purposes (old version)" do
640
675
  @ex.use { true }
641
676
  @ex.try { true }
642
677
  @ex.fabricate_durations_for_testing_purposes( "control" => 0.5, "candidate" => 1.0 )
@@ -649,7 +684,28 @@ candidate:
649
684
  assert_in_delta 1.0, cand.duration, 0.01
650
685
  end
651
686
 
652
- it "returns actual durations if fabricated ones are omitted for some blocks" do
687
+ it "allows a user to provide fabricated durations for testing purposes (new version)" do
688
+ @ex.use { true }
689
+ @ex.try { true }
690
+ @ex.fabricate_durations_for_testing_purposes({
691
+ "control" => { "duration" => 0.5, "cpu_time" => 0.4 },
692
+ "candidate" => { "duration" => 1.0, "cpu_time" => 0.9 }
693
+ })
694
+ @ex.run
695
+
696
+ cont = @ex.published_result.control
697
+ cand = @ex.published_result.candidates.first
698
+
699
+ # Wall Time
700
+ assert_in_delta 0.5, cont.duration, 0.01
701
+ assert_in_delta 1.0, cand.duration, 0.01
702
+
703
+ # CPU Time
704
+ assert_equal 0.4, cont.cpu_time
705
+ assert_equal 0.9, cand.cpu_time
706
+ end
707
+
708
+ it "returns actual durations if fabricated ones are omitted for some blocks (old version)" do
653
709
  @ex.use { true }
654
710
  @ex.try { sleep 0.1; true }
655
711
  @ex.fabricate_durations_for_testing_purposes( "control" => 0.5 )
@@ -661,5 +717,30 @@ candidate:
661
717
  assert_in_delta 0.5, cont.duration, 0.01
662
718
  assert_in_delta 0.1, cand.duration, 0.01
663
719
  end
720
+
721
+ it "returns actual durations if fabricated ones are omitted for some blocks (new version)" do
722
+ @ex.use { true }
723
+ @ex.try do
724
+ start_time = Time.now
725
+ while Time.now - start_time < 0.1
726
+ # Perform some CPU-intensive work
727
+ (1..1000).each { |i| i * i }
728
+ end
729
+ true
730
+ end
731
+ @ex.fabricate_durations_for_testing_purposes({ "control" => { "duration" => 0.5, "cpu_time" => 0.4 }})
732
+ @ex.run
733
+
734
+ cont = @ex.published_result.control
735
+ cand = @ex.published_result.candidates.first
736
+
737
+ # Fabricated durations
738
+ assert_in_delta 0.5, cont.duration, 0.01
739
+ assert_in_delta 0.4, cont.cpu_time, 0.01
740
+
741
+ # Measured durations
742
+ assert_in_delta 0.1, cand.duration, 0.01
743
+ assert_in_delta 0.1, cand.cpu_time, 0.01
744
+ end
664
745
  end
665
746
  end
@@ -6,13 +6,18 @@ describe Scientist::Observation do
6
6
 
7
7
  it "observes and records the execution of a block" do
8
8
  ob = Scientist::Observation.new("test", @experiment) do
9
- sleep 0.1
9
+ start_time = Time.now
10
+ while Time.now - start_time < 0.1
11
+ # Perform some CPU-intensive work
12
+ (1..1000).each { |i| i * i }
13
+ end
10
14
  "ret"
11
15
  end
12
16
 
13
17
  assert_equal "ret", ob.value
14
18
  refute ob.raised?
15
19
  assert_in_delta 0.1, ob.duration, 0.01
20
+ assert_in_delta 0.1, ob.cpu_time, 0.01
16
21
  end
17
22
 
18
23
  it "stashes exceptions" do
@@ -0,0 +1,4 @@
1
+ require "minitest/autorun"
2
+
3
+ $LOAD_PATH.unshift(File.expand_path(File.join(__dir__, "../lib")))
4
+ require "scientist"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scientist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.3
4
+ version: 1.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2021-12-09 00:00:00.000000000 Z
15
+ date: 2024-12-16 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: minitest
@@ -29,19 +29,19 @@ dependencies:
29
29
  - !ruby/object:Gem::Version
30
30
  version: '5.8'
31
31
  - !ruby/object:Gem::Dependency
32
- name: coveralls
32
+ name: rake
33
33
  requirement: !ruby/object:Gem::Requirement
34
34
  requirements:
35
- - - "~>"
35
+ - - ">="
36
36
  - !ruby/object:Gem::Version
37
- version: '0.8'
37
+ version: '0'
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  requirements:
42
- - - "~>"
42
+ - - ">="
43
43
  - !ruby/object:Gem::Version
44
- version: '0.8'
44
+ version: '0'
45
45
  description: A Ruby library for carefully refactoring critical paths
46
46
  email:
47
47
  - opensource+scientist@github.com
@@ -53,12 +53,14 @@ executables: []
53
53
  extensions: []
54
54
  extra_rdoc_files: []
55
55
  files:
56
+ - ".github/dependabot.yml"
57
+ - ".github/workflows/ci.yml"
56
58
  - ".gitignore"
57
- - ".travis.yml"
58
59
  - CONTRIBUTING.md
59
60
  - Gemfile
60
61
  - LICENSE.txt
61
62
  - README.md
63
+ - Rakefile
62
64
  - doc/changelog.md
63
65
  - lib/scientist.rb
64
66
  - lib/scientist/default.rb
@@ -76,6 +78,7 @@ files:
76
78
  - test/scientist/observation_test.rb
77
79
  - test/scientist/result_test.rb
78
80
  - test/scientist_test.rb
81
+ - test/test_helper.rb
79
82
  homepage: https://github.com/github/scientist
80
83
  licenses:
81
84
  - MIT
@@ -95,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
98
  - !ruby/object:Gem::Version
96
99
  version: '0'
97
100
  requirements: []
98
- rubygems_version: 3.2.32
101
+ rubygems_version: 3.5.10
99
102
  signing_key:
100
103
  specification_version: 4
101
104
  summary: Carefully test, measure, and track refactored code.
@@ -105,3 +108,4 @@ test_files:
105
108
  - test/scientist/observation_test.rb
106
109
  - test/scientist/result_test.rb
107
110
  - test/scientist_test.rb
111
+ - test/test_helper.rb
data/.travis.yml DELETED
@@ -1,14 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- script: script/test
5
- rvm:
6
- - 2.6.7
7
- - 2.7.3
8
- - 3.0.1
9
- - truffleruby-head
10
- before_install: gem install bundler
11
- addons:
12
- apt:
13
- packages:
14
- - libgmp-dev