Skip to content

Commit

Permalink
Test Repetition code even on platforms that don't trigger it/unit
Browse files Browse the repository at this point in the history
  • Loading branch information
PragTob committed May 21, 2018
1 parent 5dfea32 commit e02fd12
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 7 deletions.
7 changes: 4 additions & 3 deletions lib/benchee/benchmark/repeated_measurement.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ defmodule Benchee.Benchmark.RepeatedMeasurement do
num_iterations: num_iterations,
printer: printer
},
fast_warning
fast_warning,
measurer \\ Measure.NativeTime
) do
run_time = measure_iteration(scenario, scenario_context, Measure.NativeTime)
run_time = measure_iteration(scenario, scenario_context, measurer)

if run_time >= @minimum_execution_time do
{num_iterations, adjust_for_iterations(run_time, num_iterations)}
Expand All @@ -45,7 +46,7 @@ defmodule Benchee.Benchmark.RepeatedMeasurement do
| num_iterations: num_iterations * @times_multiplier
}

determine_n_times(scenario, new_context, false)
determine_n_times(scenario, new_context, false, measurer)
end
end

Expand Down
8 changes: 4 additions & 4 deletions lib/benchee/benchmark/runner.ex
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
defmodule Benchee.Benchmark.Runner do
@moduledoc """
This module actually runs our benchmark scenarios, adding information about
run time and memory usage to each scenario.
"""
@moduledoc false

# This module actually runs our benchmark scenarios, adding information about
# run time and memory usage to each scenario.

alias Benchee.Benchmark
alias Benchee.Benchmark.{Scenario, ScenarioContext, Measure, Hooks, RepeatedMeasurement}
Expand Down
115 changes: 115 additions & 0 deletions test/benchee/benchmark/repeated_measurement_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
defmodule Bencheee.Benchmark.RepeatedMeasurementTest.FakeMeasurer do
@behaviour Benchee.Benchmark.Measure

def measure(function) do
value = function.()
time = Process.get(:test_measurement_time, 5)
next_value = time * 10

Process.put(:test_measurement_time, next_value)

{time, value}
end
end

defmodule Bencheee.Benchmark.RepeatedMeasurementTest do
use ExUnit.Case

import Benchee.Benchmark.RepeatedMeasurement
alias Benchee.Benchmark.{Scenario, ScenarioContext}
alias Benchee.Test.FakeBenchmarkPrinter
alias Bencheee.Benchmark.RepeatedMeasurementTest.FakeMeasurer

@no_input Benchee.Benchmark.no_input()
@scenario_context %ScenarioContext{
num_iterations: 1,
printer: FakeBenchmarkPrinter,
config: %Benchee.Configuration{},
scenario_input: @no_input
}

describe ".determine_n_times/4" do
test "it repeats the function calls until a suitable time is reached" do
function = fn -> send(self(), :called) end
scenario = %Scenario{function: function}
{num_iterations, time} = determine_n_times(scenario, @scenario_context, false, FakeMeasurer)

assert num_iterations == 10
assert time == 5 # 50 adjusted by the 10 iteration factor

assert_received_exactly_n_times(:called, 11) # 1 initial + 10 more after repeat
end

test "doesn't do repetitions if the time is small enough from the get go" do
function = fn -> send(self(), :called) end
scenario = %Scenario{function: function}
Process.put(:test_measurement_time, 10)

{num_iterations, time} = determine_n_times(scenario, @scenario_context, false, FakeMeasurer)

assert num_iterations == 1
assert time == 10

assert_received_exactly_n_times(:called, 1) # 1 initial + 10 more after repeat
end
end

describe ".measure" do
test "scales reported times approproately" do
scenario_context = %ScenarioContext{
@scenario_context
| num_iterations: 10,
}
scenario = %Scenario{
input: @no_input,
function: fn -> 42 end
}
Process.put(:test_measurement_time, 50)

time = measure(scenario, scenario_context, FakeMeasurer)

assert time == 5
end

test "calls hooks appropriately even with multiple iterations" do
num_iterations = 10
scenario_context = %ScenarioContext{
@scenario_context
| num_iterations: num_iterations,
config: %Benchee.Configuration{
before_each: fn _ ->
send self(), :global_before
@no_input
end,
after_each: fn _ -> send self(), :global_after end
}
}
scenario = %Scenario{
input: @no_input,
function: fn -> send(self(), :called) end,
before_each: fn _ ->
send self(), :local_before
@no_input
end,
after_each: fn _ -> send self(), :local_after end
}
Process.put(:test_measurement_time, 50)

time = measure(scenario, scenario_context, FakeMeasurer)

assert time == 5

expected_messages = [:global_before, :local_before, :called, :local_after, :global_after]

Enum.each(expected_messages, fn message ->
assert_received_exactly_n_times(message, num_iterations)
end)
end
end

defp assert_received_exactly_n_times(message, count) do
Enum.each(1..count, fn _ -> assert_received ^message end)

refute_received ^message
end
end

0 comments on commit e02fd12

Please sign in to comment.