scientist 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +17 -0
- data/lib/scientist.rb +24 -2
- data/lib/scientist/default.rb +2 -2
- data/lib/scientist/version.rb +1 -1
- data/script/release +1 -1
- data/test/scientist/default_test.rb +2 -2
- data/test/scientist/experiment_test.rb +5 -0
- data/test/scientist_test.rb +9 -0
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2ad0ca94921ed85fa82b13057d4c68c842d42ea256df543b32196e665c75519c
|
4
|
+
data.tar.gz: 02f8948568c02e57d003b42a7ca4964e78e1ca14df57b6f204c2db31be5098a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 671d170da1739b46f102a898a32b522438f45323cc1d2b788865566bfc2c16d16c6b364c4610a97ee30e4da597642bb4ad9d2c422384eddbab278ae170469f9f
|
7
|
+
data.tar.gz: 5334f5ae2d735cdc3b230bfefd469bd51c9e9363ec5cec83d45e99cbb2b3b55fa14f057dc59dc7909828dc0182c9168c9a86d47efe5529971206b9ff5c14a52a
|
data/README.md
CHANGED
@@ -394,6 +394,10 @@ Because `enabled?` and `run_if` determine when a candidate runs, it's impossible
|
|
394
394
|
|
395
395
|
When using Scientist, we've found it most useful to modify both the existing and new systems simultaneously anywhere writes happen, and verify the results at read time with `science`. `raise_on_mismatches` has also been useful to ensure that the correct data was written during tests, and reviewing published mismatches has helped us find any situations we overlooked with our production data at runtime. When writing to and reading from two systems, it's also useful to write some data reconciliation scripts to verify and clean up production data alongside any running experiments.
|
396
396
|
|
397
|
+
#### Noise and error rates
|
398
|
+
|
399
|
+
Keep in mind that Scientist's `try` and `use` blocks run sequentially in random order. As such, any data upon which your code depends may change before the second block is invoked, potentially yielding a mismatch between the candidate and control return values. To calibrate your expectations with respect to [false negatives](https://en.wikipedia.org/wiki/Type_I_and_type_II_errors) arising from systemic conditions external to your proposed changes, consider starting with an experiment in which both the `try` and `use` blocks invoke the control method. Then proceed with introducing a candidate.
|
400
|
+
|
397
401
|
### Finishing an experiment
|
398
402
|
|
399
403
|
As your candidate behavior converges on the controls, you'll start thinking about removing an experiment and using the new behavior.
|
@@ -458,6 +462,17 @@ science "various-ways", run: "first-way" do |e|
|
|
458
462
|
end
|
459
463
|
```
|
460
464
|
|
465
|
+
### Without including Scientist
|
466
|
+
|
467
|
+
If you need to use Scientist in a place where you aren't able to include the Scientist module, you can call `Scientist.run`:
|
468
|
+
|
469
|
+
```ruby
|
470
|
+
Scientist.run "widget-permissions" do |e|
|
471
|
+
e.use { model.check_user(user).valid? }
|
472
|
+
e.try { user.can?(:read, model) }
|
473
|
+
end
|
474
|
+
```
|
475
|
+
|
461
476
|
## Hacking
|
462
477
|
|
463
478
|
Be on a Unixy box. Make sure a modern Bundler is available. `script/test` runs the unit tests. All development dependencies are installed automatically. Science requires Ruby 1.9 or newer.
|
@@ -477,6 +492,8 @@ Be on a Unixy box. Make sure a modern Bundler is available. `script/test` runs t
|
|
477
492
|
- [MadcapJake/Test-Lab](https://github.com/MadcapJake/Test-Lab) (Perl 6)
|
478
493
|
- [cwbriones/scientist](https://github.com/cwbriones/scientist) (Elixir)
|
479
494
|
- [calavera/go-scientist](https://github.com/calavera/go-scientist) (Go)
|
495
|
+
- [jelmersnoeck/experiment](https://github.com/jelmersnoeck/experiment) (Go)
|
496
|
+
- [spoptchev/scientist](https://github.com/spoptchev/scientist) (Kotlin / Java)
|
480
497
|
|
481
498
|
|
482
499
|
## Maintainers
|
data/lib/scientist.rb
CHANGED
@@ -3,6 +3,9 @@
|
|
3
3
|
# defining and running experiments.
|
4
4
|
#
|
5
5
|
# If you need to run science on class methods, extend this module instead.
|
6
|
+
#
|
7
|
+
# If including or extending this module are not an option, call
|
8
|
+
# `Scientist.run`.
|
6
9
|
module Scientist
|
7
10
|
# Define and run a science experiment.
|
8
11
|
#
|
@@ -15,9 +18,8 @@ module Scientist
|
|
15
18
|
#
|
16
19
|
# Returns the calculated value of the control experiment, or raises if an
|
17
20
|
# exception was raised.
|
18
|
-
def
|
21
|
+
def self.run(name, opts = {})
|
19
22
|
experiment = Experiment.new(name)
|
20
|
-
experiment.context(default_scientist_context)
|
21
23
|
|
22
24
|
yield experiment
|
23
25
|
|
@@ -25,6 +27,26 @@ module Scientist
|
|
25
27
|
experiment.run(test)
|
26
28
|
end
|
27
29
|
|
30
|
+
# Define and run a science experiment.
|
31
|
+
#
|
32
|
+
# name - a String name for this experiment.
|
33
|
+
# opts - optional hash with the the named test to run instead of "control",
|
34
|
+
# :run is the only valid key.
|
35
|
+
#
|
36
|
+
# Yields an object which implements the Scientist::Experiment interface.
|
37
|
+
# See `Scientist::Experiment.new` for how this is defined. The context from
|
38
|
+
# the `default_scientist_context` method will be applied to the experiment.
|
39
|
+
#
|
40
|
+
# Returns the calculated value of the control experiment, or raises if an
|
41
|
+
# exception was raised.
|
42
|
+
def science(name, opts = {})
|
43
|
+
Scientist.run(name, opts) do |experiment|
|
44
|
+
experiment.context(default_scientist_context)
|
45
|
+
|
46
|
+
yield experiment
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
28
50
|
# Public: the default context data for an experiment created and run via the
|
29
51
|
# `science` helper method. Override this in any class that includes Scientist
|
30
52
|
# to define your own behavior.
|
data/lib/scientist/default.rb
CHANGED
data/lib/scientist/version.rb
CHANGED
data/script/release
CHANGED
@@ -123,6 +123,11 @@ describe Scientist::Experiment do
|
|
123
123
|
it "re-raises exceptions raised during publish by default" do
|
124
124
|
ex = Scientist::Experiment.new("hello")
|
125
125
|
assert_kind_of Scientist::Default, ex
|
126
|
+
|
127
|
+
def ex.enabled?
|
128
|
+
true
|
129
|
+
end
|
130
|
+
|
126
131
|
def ex.publish(result)
|
127
132
|
raise "boomtown"
|
128
133
|
end
|
data/test/scientist_test.rb
CHANGED
@@ -15,6 +15,15 @@ describe Scientist do
|
|
15
15
|
assert_equal :control, r
|
16
16
|
end
|
17
17
|
|
18
|
+
it "provides a module method to instantiate and run experiments" do
|
19
|
+
r = Scientist.run "test" do |e|
|
20
|
+
e.use { :control }
|
21
|
+
e.try { :candidate }
|
22
|
+
end
|
23
|
+
|
24
|
+
assert_equal :control, r
|
25
|
+
end
|
26
|
+
|
18
27
|
it "provides an empty default_scientist_context" do
|
19
28
|
obj = Object.new
|
20
29
|
obj.extend(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.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub Open Source
|
@@ -12,34 +12,34 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2018-02-06 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: minitest
|
19
19
|
requirement: !ruby/object:Gem::Requirement
|
20
20
|
requirements:
|
21
|
-
- - ~>
|
21
|
+
- - "~>"
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: '5.8'
|
24
24
|
type: :development
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
|
-
- - ~>
|
28
|
+
- - "~>"
|
29
29
|
- !ruby/object:Gem::Version
|
30
30
|
version: '5.8'
|
31
31
|
- !ruby/object:Gem::Dependency
|
32
32
|
name: coveralls
|
33
33
|
requirement: !ruby/object:Gem::Requirement
|
34
34
|
requirements:
|
35
|
-
- - ~>
|
35
|
+
- - "~>"
|
36
36
|
- !ruby/object:Gem::Version
|
37
37
|
version: '0.8'
|
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
44
|
version: '0.8'
|
45
45
|
description: A Ruby library for carefully refactoring critical paths
|
@@ -53,8 +53,8 @@ executables: []
|
|
53
53
|
extensions: []
|
54
54
|
extra_rdoc_files: []
|
55
55
|
files:
|
56
|
-
- .gitignore
|
57
|
-
- .travis.yml
|
56
|
+
- ".gitignore"
|
57
|
+
- ".travis.yml"
|
58
58
|
- Gemfile
|
59
59
|
- LICENSE.txt
|
60
60
|
- README.md
|
@@ -85,17 +85,17 @@ require_paths:
|
|
85
85
|
- lib
|
86
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- -
|
88
|
+
- - ">="
|
89
89
|
- !ruby/object:Gem::Version
|
90
90
|
version: '0'
|
91
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
|
-
- -
|
93
|
+
- - ">="
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
version: '0'
|
96
96
|
requirements: []
|
97
97
|
rubyforge_project:
|
98
|
-
rubygems_version: 2.
|
98
|
+
rubygems_version: 2.7.3
|
99
99
|
signing_key:
|
100
100
|
specification_version: 4
|
101
101
|
summary: Carefully test, measure, and track refactored code.
|