diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 89ec9ac..18a1ecc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,9 +10,9 @@ Contributions to this project are [released](https://help.github.com/articles/gi ## Submitting a pull request 0. [Fork][fork] and clone the repository -0. Create a new branch: `git checkout -b my-branch-name` -0. Make your change, push to your fork and [submit a pull request][pr] -0. Pat your self on the back and wait for your pull request to be reviewed and merged. +1. Create a new branch: `git checkout -b my-branch-name` +2. Make your change, push to your fork and [submit a pull request][pr] +3. Pat your self on the back and wait for your pull request to be reviewed and merged. Here are a few things you can do that will increase the likelihood of your pull request being accepted: diff --git a/lib/scientist/experiment.rb b/lib/scientist/experiment.rb index ec35a3a..614bf6f 100644 --- a/lib/scientist/experiment.rb +++ b/lib/scientist/experiment.rb @@ -84,6 +84,7 @@ def raise_on_mismatches? # # Returns the configured block. def before_run(&block) + marshalize(block) @_scientist_before_run = block end @@ -99,6 +100,7 @@ def behaviors # # Returns the configured block. def clean(&block) + marshalize(block) @_scientist_cleaner = block end @@ -131,6 +133,7 @@ def clean_value(value) # # Returns the block. def compare(*args, &block) + marshalize(block) @_scientist_comparator = block end @@ -141,6 +144,7 @@ def compare(*args, &block) # # Returns the block. def compare_errors(*args, &block) + marshalize(block) @_scientist_error_comparator = block end @@ -159,6 +163,7 @@ def context(context = nil) # # This can be called more than once with different blocks to use. def ignore(&block) + marshalize(block) @_scientist_ignores ||= [] @_scientist_ignores << block end @@ -251,6 +256,7 @@ def run(name = nil) # Define a block that determines whether or not the experiment should run. def run_if(&block) + marshalize(block) @_scientist_run_if_block = block end @@ -276,6 +282,7 @@ def should_experiment_run? # Register a named behavior for this experiment, default "candidate". def try(name = nil, &block) + marshalize(block) name = (name || "candidate").to_s if behaviors.include?(name) @@ -287,6 +294,7 @@ def try(name = nil, &block) # Register the control behavior for this experiment. def use(&block) + marshalize(block) try "control", &block end @@ -318,4 +326,19 @@ def generate_result(name) control = observations.detect { |o| o.name == name } Scientist::Result.new(self, observations, control) end + + private + + # In order to support marshaling, we have to make the procs marshalable. Some + # CI providers attempt to marshal Scientist mismatch errors so that they can + # be sent out to different places (logs, etc.) The mismatch errors contain + # code from the experiment. This code contains Procs - which can't be + # marshaled until we run the following code. + def marshalize(block) + unless block.respond_to?(:_dump) || block.respond_to?(:_dump_data) + def block._dump(_) + to_s + end + end + end end diff --git a/test/scientist/experiment_test.rb b/test/scientist/experiment_test.rb index e102473..12462f6 100644 --- a/test/scientist/experiment_test.rb +++ b/test/scientist/experiment_test.rb @@ -491,6 +491,27 @@ def @ex.raised(op, exception) assert_raises(Scientist::Experiment::MismatchError) { runner.call } end + it "can be marshaled" do + Fake.raise_on_mismatches = true + @ex.before_run { "some block" } + @ex.clean { "some block" } + @ex.compare_errors { "some block" } + @ex.ignore { false } + @ex.run_if { "some block" } + @ex.try { "candidate" } + @ex.use { "control" } + @ex.compare { |control, candidate| control == candidate } + + mismatch = nil + begin + @ex.run + rescue Scientist::Experiment::MismatchError => e + mismatch = e + end + + assert_kind_of(String, Marshal.dump(mismatch)) + end + describe "#raise_on_mismatches?" do it "raises when there is a mismatch if the experiment instance's raise on mismatches is enabled" do Fake.raise_on_mismatches = false