scientist 1.6.0 → 1.6.4

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: f03841ae9bccb8d7b979971d5f6a38482f57bbc81af82d0a710479ccc3f16fbb
4
- data.tar.gz: c0f81d696918e302462baf1bd918cd25179a99045d48082fb162e1fdb2fa2280
3
+ metadata.gz: 5553615794cee9e0fbdb4c22b3dd528885b30a75c9c8c2bd1d5d4f8ebd4bc0ba
4
+ data.tar.gz: ff1c3e2b2f23defc19ad663df792da483926406aa98261d403fa7c008c03be85
5
5
  SHA512:
6
- metadata.gz: f1680e6564a6e83b3dde55f6757f3e7c953a70b3d748aa0e7ca2a54b5a33a4b3a947a8f20aa52790a41e6a66e36627e4e851f627625c0aaf9fd4cf41b94ace8c
7
- data.tar.gz: 75ba381053b73e9418ed2ab5608c70c92a55990c938a1c25f4324169ff560a8feea6827ef909e50b9fc3baf5a5eb49f3b7b26ed4e3f9799007b80a71c7543c86
6
+ metadata.gz: ffef7682cdd59612ca44b33ba3678467251c2ccabfdecda41022cc95c0d07673abd38ca3a33c357fa40358398691ba0f8ecf8ec04ddff14800a25a915f011f4d
7
+ data.tar.gz: 06e06b1428967829d9b330eba28bd1bd2ce47eb5b12b6317eb6c6e8ea53e4e6434337803b88fdadbccdcb23a1b8cafe2fbe98a38756ea53d81ed21afe0ec369e
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -0,0 +1,33 @@
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
+ steps:
28
+ - uses: actions/checkout@v3
29
+ - uses: ruby/setup-ruby@v1
30
+ with:
31
+ ruby-version: ${{ matrix.ruby_version }}
32
+ bundler-cache: true
33
+ - run: bundle exec rake
data/CONTRIBUTING.md CHANGED
@@ -10,9 +10,9 @@ Contributions to this project are [released](https://help.github.com/articles/gi
10
10
  ## Submitting a pull request
11
11
 
12
12
  0. [Fork][fork] and clone the repository
13
- 0. Create a new branch: `git checkout -b my-branch-name`
14
- 0. Make your change, push to your fork and [submit a pull request][pr]
15
- 0. Pat your self on the back and wait for your pull request to be reviewed and merged.
13
+ 1. Create a new branch: `git checkout -b my-branch-name`
14
+ 2. Make your change, push to your fork and [submit a pull request][pr]
15
+ 3. Pat your self on the back and wait for your pull request to be reviewed and merged.
16
16
 
17
17
  Here are a few things you can do that will increase the likelihood of your pull request being accepted:
18
18
 
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
 
@@ -84,7 +84,7 @@ class MyExperiment
84
84
  end
85
85
  ```
86
86
 
87
- When `Scientist::Experiment` is included in a class, it automatically sets it as the default implementation via `Scientist::Experiment.set_default`. This `set_default` call is is skipped if you include `Scientist::Experiment` in a module.
87
+ When `Scientist::Experiment` is included in a class, it automatically sets it as the default implementation via `Scientist::Experiment.set_default`. This `set_default` call is skipped if you include `Scientist::Experiment` in a module.
88
88
 
89
89
  Now calls to the `science` helper will load instances of `MyExperiment`.
90
90
 
@@ -109,6 +109,38 @@ 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_errors` to define how to compare observed errors instead:
113
+
114
+ ```ruby
115
+ class MyWidget
116
+ include Scientist
117
+
118
+ def slug_from_login(login)
119
+ science "slug_from_login" do |e|
120
+ e.use { User.slug_from_login login } # returns String instance or ArgumentError
121
+ e.try { UserService.slug_from_login login } # returns String instance or ArgumentError
122
+
123
+ compare_error_message_and_class = -> (control, candidate) do
124
+ control.class == candidate.class &&
125
+ control.message == candidate.message
126
+ end
127
+
128
+ compare_argument_errors = -> (control, candidate) do
129
+ control.class == ArgumentError &&
130
+ candidate.class == ArgumentError &&
131
+ control.message.start_with?("Input has invalid characters") &&
132
+ candidate.message.start_with?("Invalid characters in input")
133
+ end
134
+
135
+ e.compare_errors do |control, candidate|
136
+ compare_error_message_and_class.call(control, candidate) ||
137
+ compare_argument_errors.call(control, candidate)
138
+ end
139
+ end
140
+ end
141
+ end
142
+ ```
143
+
112
144
  ### Adding context
113
145
 
114
146
  Results aren't very useful without some way to identify them. Use the `context` method to add to or retrieve the context for an experiment:
@@ -228,7 +260,7 @@ def admin?(user)
228
260
  end
229
261
  ```
230
262
 
231
- The ignore blocks are only called if the *values* don't match. If one observation raises an exception and the other doesn't, it's always considered a mismatch. If both observations raise different exceptions, that is also considered a mismatch.
263
+ 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.
232
264
 
233
265
  ### Enabling/disabling experiments
234
266
 
@@ -395,6 +427,8 @@ Scientist rescues and tracks _all_ exceptions raised in a `try` or `use` block,
395
427
  Scientist::Observation::RESCUES.replace [StandardError]
396
428
  ```
397
429
 
430
+ **Timeout ⏲️**: If you're introducing a candidate that could possibly timeout, use caution. ⚠️ While Scientist rescues all exceptions that occur in the candidate block, it *does not* protect you from timeouts, as doing so would be complicated. It would likely require running the candidate code in a background job and tracking the time of a request. We feel the cost of this complexity would outweigh the benefit, so make sure that your code doesn't cause timeouts. This risk can be reduced by running the experiment on a low percentage so that users can (most likely) bypass the experiment by refreshing the page if they hit a timeout. See [Ramping up experiments](#ramping-up-experiments) below for how details on how to set the percentage for your experiment.
431
+
398
432
  #### In a Scientist callback
399
433
 
400
434
  If an exception is raised within any of Scientist's internal helpers, like `publish`, `compare`, or `clean`, the `raised` method is called with the symbol name of the internal operation that failed and the exception that was raised. The default behavior of `Scientist::Default` is to simply re-raise the exception. Since this halts the experiment entirely, it's often a better idea to handle this error and continue so the experiment as a whole isn't canceled entirely:
@@ -551,6 +585,7 @@ Be on a Unixy box. Make sure a modern Bundler is available. `script/test` runs t
551
585
  - [junkpiano/scientist](https://github.com/junkpiano/scientist) (Swift)
552
586
  - [serverless scientist](http://serverlessscientist.com/) (AWS Lambda)
553
587
  - [fightmegg/scientist](https://github.com/fightmegg/scientist) (TypeScript, Browser / Node.js)
588
+ - [MisterSpex/misterspex-scientist](https://github.com/MisterSpex/misterspex-scientist) (Java, no dependencies)
554
589
 
555
590
  ## Maintainers
556
591
 
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
@@ -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
@@ -134,6 +144,16 @@ module Scientist::Experiment
134
144
  @_scientist_comparator = block
135
145
  end
136
146
 
147
+ # A block which compares two experimental errors.
148
+ #
149
+ # The block must take two arguments, the control Error and a candidate Error,
150
+ # and return true or false.
151
+ #
152
+ # Returns the block.
153
+ def compare_errors(*args, &block)
154
+ @_scientist_error_comparator = block
155
+ end
156
+
137
157
  # A Symbol-keyed Hash of extra experiment data.
138
158
  def context(context = nil)
139
159
  @_scientist_context ||= {}
@@ -177,13 +197,9 @@ module Scientist::Experiment
177
197
  "experiment"
178
198
  end
179
199
 
180
- # Internal: compare two observations, using the configured compare block if present.
200
+ # Internal: compare two observations, using the configured compare and compare_errors lambdas if present.
181
201
  def observations_are_equivalent?(a, b)
182
- if @_scientist_comparator
183
- a.equivalent_to?(b, &@_scientist_comparator)
184
- else
185
- a.equivalent_to? b
186
- end
202
+ a.equivalent_to? b, @_scientist_comparator, @_scientist_error_comparator
187
203
  rescue StandardError => ex
188
204
  raised :compare, ex
189
205
  false
@@ -224,6 +240,10 @@ module Scientist::Experiment
224
240
 
225
241
  result = generate_result(name)
226
242
 
243
+ if @_scientist_after_run
244
+ @_scientist_after_run.call(result)
245
+ end
246
+
227
247
  begin
228
248
  publish(result)
229
249
  rescue StandardError => ex
@@ -312,4 +332,20 @@ module Scientist::Experiment
312
332
  control = observations.detect { |o| o.name == name }
313
333
  Scientist::Result.new(self, observations, control)
314
334
  end
335
+
336
+ private
337
+
338
+ # In order to support marshaling, we have to make the procs marshalable. Some
339
+ # CI providers attempt to marshal Scientist mismatch errors so that they can
340
+ # be sent out to different places (logs, etc.) The mismatch errors contain
341
+ # code from the experiment. This code contains procs. These procs prevent the
342
+ # error from being marshaled. To fix this, we simple exclude the procs from
343
+ # the data that we marshal.
344
+ def marshal_dump
345
+ [@name, @result, @raise_on_mismatches]
346
+ end
347
+
348
+ def marshal_load
349
+ @name, @result, @raise_on_mismatches = array
350
+ end
315
351
  end
@@ -45,25 +45,34 @@ class Scientist::Observation
45
45
 
46
46
  # Is this observation equivalent to another?
47
47
  #
48
- # other - the other Observation in question
49
- # comparator - an optional comparison block. This observation's value and the
50
- # other observation's value are yielded to this to determine
51
- # their equivalency. Block should return true/false.
48
+ # other - the other Observation in question
49
+ # comparator - an optional comparison proc. This observation's value and the
50
+ # other observation's value are passed to this to determine
51
+ # their equivalency. Proc should return true/false.
52
+ # error_comparator - an optional comparison proc. This observation's Error and the
53
+ # other observation's Error are passed to this to determine
54
+ # their equivalency. Proc should return true/false.
52
55
  #
53
56
  # Returns true if:
54
57
  #
55
58
  # * The values of the observation are equal (using `==`)
56
59
  # * The values of the observations are equal according to a comparison
57
- # block, if given
60
+ # proc, if given
61
+ # * The exceptions raised by the observations are equal according to the
62
+ # error comparison proc, if given.
58
63
  # * Both observations raised an exception with the same class and message.
59
64
  #
60
65
  # Returns false otherwise.
61
- def equivalent_to?(other, &comparator)
66
+ def equivalent_to?(other, comparator=nil, error_comparator=nil)
62
67
  return false unless other.is_a?(Scientist::Observation)
63
68
 
64
69
  if raised? || other.raised?
65
- return other.exception.class == exception.class &&
66
- other.exception.message == exception.message
70
+ if error_comparator
71
+ return error_comparator.call(exception, other.exception)
72
+ else
73
+ return other.exception.class == exception.class &&
74
+ other.exception.message == exception.message
75
+ end
67
76
  end
68
77
 
69
78
  if comparator
@@ -1,3 +1,3 @@
1
1
  module Scientist
2
- VERSION = "1.6.0"
2
+ VERSION = '1.6.4'
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/release CHANGED
@@ -12,10 +12,10 @@ cd $(dirname "$0")/..
12
12
  rm -rf scientist-*.gem
13
13
  gem build -q scientist.gemspec
14
14
 
15
- # Make sure we're on the master branch.
15
+ # Make sure we're on the main branch.
16
16
 
17
- (git branch --no-color | grep -q '* master') || {
18
- echo "Only release from the master branch."
17
+ (git branch --no-color | grep -q '* main') || {
18
+ echo "Only release from the main branch."
19
19
  exit 1
20
20
  }
21
21
 
@@ -35,4 +35,4 @@ git fetch -t origin
35
35
  # Tag it and bag it.
36
36
 
37
37
  gem push scientist-*.gem && git tag "$tag" &&
38
- git push origin master && git push origin "$tag"
38
+ git push origin main && git push origin "$tag"
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
@@ -201,6 +201,18 @@ describe Scientist::Experiment do
201
201
  assert @ex.published_result.matched?
202
202
  end
203
203
 
204
+ it "compares errors with an error comparator block if provided" do
205
+ @ex.compare_errors { |a, b| a.class == b.class }
206
+ @ex.use { raise "foo" }
207
+ @ex.try { raise "bar" }
208
+
209
+ resulting_error = assert_raises RuntimeError do
210
+ @ex.run
211
+ end
212
+ assert_equal "foo", resulting_error.message
213
+ assert @ex.published_result.matched?
214
+ end
215
+
204
216
  it "knows how to compare two experiments" do
205
217
  a = Scientist::Observation.new(@ex, "a") { 1 }
206
218
  b = Scientist::Observation.new(@ex, "b") { 2 }
@@ -479,6 +491,27 @@ describe Scientist::Experiment do
479
491
  assert_raises(Scientist::Experiment::MismatchError) { runner.call }
480
492
  end
481
493
 
494
+ it "can be marshaled" do
495
+ Fake.raise_on_mismatches = true
496
+ @ex.before_run { "some block" }
497
+ @ex.clean { "some block" }
498
+ @ex.compare_errors { "some block" }
499
+ @ex.ignore { false }
500
+ @ex.run_if { "some block" }
501
+ @ex.try { "candidate" }
502
+ @ex.use { "control" }
503
+ @ex.compare { |control, candidate| control == candidate }
504
+
505
+ mismatch = nil
506
+ begin
507
+ @ex.run
508
+ rescue Scientist::Experiment::MismatchError => e
509
+ mismatch = e
510
+ end
511
+
512
+ assert_kind_of(String, Marshal.dump(mismatch))
513
+ end
514
+
482
515
  describe "#raise_on_mismatches?" do
483
516
  it "raises when there is a mismatch if the experiment instance's raise on mismatches is enabled" do
484
517
  Fake.raise_on_mismatches = false
@@ -602,6 +635,37 @@ candidate:
602
635
  end
603
636
  end
604
637
 
638
+ describe "after run block" do
639
+ it "runs when an experiment is enabled" do
640
+ control_ok = candidate_ok = false
641
+ after_result = nil
642
+ @ex.after_run { |result| after_result = result }
643
+ @ex.use { control_ok = after_result.nil? }
644
+ @ex.try { candidate_ok = after_result.nil? }
645
+
646
+ @ex.run
647
+
648
+ assert after_result, "after_run should have run"
649
+ assert after_result.matched?, "after_run should be called with the result"
650
+ assert control_ok, "control should have run before after_run"
651
+ assert candidate_ok, "candidate should have run before after_run"
652
+ end
653
+
654
+ it "does not run when an experiment is disabled" do
655
+ after_result = nil
656
+
657
+ def @ex.enabled?
658
+ false
659
+ end
660
+ @ex.after_run { |result| after_result = result }
661
+ @ex.use { "value" }
662
+ @ex.try { "value" }
663
+ @ex.run
664
+
665
+ refute after_result, "after_run should not have run"
666
+ end
667
+ end
668
+
605
669
  describe "testing hooks for extending code" do
606
670
  it "allows a user to provide fabricated durations for testing purposes" do
607
671
  @ex.use { true }
@@ -80,7 +80,7 @@ describe Scientist::Observation do
80
80
  refute x.equivalent_to?(y)
81
81
  end
82
82
 
83
- FirstErrror = Class.new(StandardError)
83
+ FirstError = Class.new(StandardError)
84
84
  SecondError = Class.new(StandardError)
85
85
 
86
86
  it "compares exception classes" do
@@ -92,22 +92,46 @@ describe Scientist::Observation do
92
92
  refute x.equivalent_to?(y)
93
93
  end
94
94
 
95
- it "compares values using a comparator block" do
95
+ it "compares values using a comparator proc" do
96
96
  a = Scientist::Observation.new("test", @experiment) { 1 }
97
97
  b = Scientist::Observation.new("test", @experiment) { "1" }
98
98
 
99
99
  refute a.equivalent_to?(b)
100
- assert a.equivalent_to?(b) { |x, y| x.to_s == y.to_s }
100
+
101
+ compare_on_string = -> (x, y) { x.to_s == y.to_s }
102
+
103
+ assert a.equivalent_to?(b, compare_on_string)
101
104
 
102
105
  yielded = []
103
- a.equivalent_to?(b) do |x, y|
106
+ compare_appends = -> (x, y) do
104
107
  yielded << x
105
108
  yielded << y
106
109
  true
107
110
  end
111
+ a.equivalent_to?(b, compare_appends)
112
+
108
113
  assert_equal [a.value, b.value], yielded
109
114
  end
110
115
 
116
+ it "compares exceptions using an error comparator proc" do
117
+ x = Scientist::Observation.new("test", @experiment) { raise FirstError, "error" }
118
+ y = Scientist::Observation.new("test", @experiment) { raise SecondError, "error" }
119
+ z = Scientist::Observation.new("test", @experiment) { raise FirstError, "ERROR" }
120
+
121
+ refute x.equivalent_to?(z)
122
+ refute x.equivalent_to?(y)
123
+
124
+ compare_on_class = -> (error, other_error) {
125
+ error.class == other_error.class
126
+ }
127
+ compare_on_message = -> (error, other_error) {
128
+ error.message == other_error.message
129
+ }
130
+
131
+ assert x.equivalent_to?(z, nil, compare_on_class)
132
+ assert x.equivalent_to?(y, nil, compare_on_message)
133
+ end
134
+
111
135
  describe "#cleaned_value" do
112
136
  it "returns the observation's value by default" do
113
137
  a = Scientist::Observation.new("test", @experiment) { 1 }
@@ -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.0
4
+ version: 1.6.4
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-03-08 00:00:00.000000000 Z
15
+ date: 2023-04-05 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.1.4
101
+ rubygems_version: 3.3.7
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,15 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- script: script/test
5
- rvm:
6
- - 2.3.8
7
- - 2.4.5
8
- - 2.5.3
9
- - 2.6.1
10
- - truffleruby-head
11
- before_install: gem install bundler
12
- addons:
13
- apt:
14
- packages:
15
- - libgmp-dev