🏝 automated contract testing via type checking for Elixir functions and mocks
[#120]
Hammox now includes telemetry events! See Telemetry Guide for more information.
Big thanks to @SophisticaSean for carrying this start to finish!
[#103]
Hammox now uses :persistent_term instead of a GenServer for caching typespecs, resulting in a ~5x speedup. Thanks @SophisticaSean for making and benchmarking the changes and @Adzz for suggesting :persistent_term!
Hammox.Protect
and Hammox.protect/2
[#93]use Hammox.Protect
now accepts multiple :behaviour
options:
use Hammox.Protect, module: My.Module, behaviour: My.Module.Contract, behaviour: My.Module.OtherContract
Which is functionally equivalent to:
use Hammox.Protect, module: My.Module, behaviour: My.Module.Contract
use Hammox.Protect, module: My.Module, behaviour: My.Module.OtherContract
Likewise, Hammox.protect/2
now additionally supports a list of behaviours as second argument:
Hammox.protect(My.Module, [My.Module.Contract, My.Module.OtherContract]),
Big thanks to @camilleryr for submitting these changes.
bool()
type is now correctly supported and no longer causes an exception [#115]Code.ensure_compiled/1
[#111] (thanks to @Adzz)[#71]
You can now do use Hammox.Protect
instead of calling Hammox.protect/3
directly as a less verbose way of creating protected functions in tests. See the Hammox.Protect API docs for more details and the README for an example.
:ordinal
0.1.0
-> 0.2.0
[#68]The biggest release yet!
[#53]
Hammox v0.2 and below was completely stateless. Any time a Hammox-protected function was called, types needed to be read from disk and parsed from the compiled binary files. This created a huge bottleneck which given complex typespecs with many types slowed down Hammox-heavy test suites considerably.
Hammox v0.3 includes a typespec cache server and keeps all types in memory once first read from disk. Now the performance impact is practically indistinguishable from Mox.
[#54] [#55]
When using the "batch" version of protect
where you pass an implementation module, a behaviour module, and a list of functions, the list of functions is now optional. Hammox will decorate all functions from the behaviour by default.
Example:
defmodule Calculator do
@callback add(integer(), integer()) :: integer()
end
defmodule TestCalculator do
def add(a, b), do: a + b
end
# Hammox v0.2
Hammox.protect(TestCalculator, Calculator, add: 2)
# Hammox v0.3
Hammox.protect(TestCalculator, Calculator)
[#51] [#62]
When using modules which contain both callbacks and implementations, you now only need to pass the module to protect
once.
Example:
defmodule Calculator do
@callback add(integer(), integer()) :: integer()
def add(a, b), do: a + b
end
# Hammox v0.2
Hammox.protect(Calculator, Calculator, add: 2)
# Hammox v0.3
Hammox.protect(Calculator, add: 2)
protect
edge cases[#52]
Before, passing nonexistent module to protect
resulted in an ugly internal exception. Now, we raise a better exception explaning what happened.
[#58]
Before, calls to stubs created by Hammox were not being type checked. This was an oversight. In Hammox v0.3, calls to stubs created by Hammox using Hammox.stub/3
are type checked.
[#50]
Hammox v0.3 now includes Mox 1.0.0.
Thanks to @saneery, @randycoulman, @jotaviobiondo and @SophisticaSean for helping make this release happen!