Skip to content

Improve testing experience for Oban and its plugins #632

@milmazz

Description

@milmazz

Is your feature request related to a problem? Please describe.

This is not an actual problem because you can now find workarounds to test your Oban configuration and some of the plugin configurations. But I'm sure we can improve the experience around these things.

For example, to test your Oban configuration, you can do something like:

defmodule MyApp.ObanConfigTest do
  use ExUnit.Case, async: true

 test "check oban configuration" do
    [config, prod] =
      Enum.map(["config/config.exs", "config/prod.exs"], fn path ->
        path
        |> Config.Reader.read!(imports: [], env: :prod, target: :host)
        |> get_in([:core, Oban])
      end)

    assert %Oban.Config{plugins: _plugins} = config |> Keyword.merge(prod) |> Oban.Config.new()
  end
end

But, for the previous unit test to make sense, you need to know a bit of the internal implementation of Oban, which is the use of the inner function Oban.Config.new/1.

It is important to note that the Oban.Config.new/1 function doesn't validate the internal configuration for the plugins; it only validates that the given plugin is an atom, is loaded, the plugin in question exports an init/1 function, and also the given opts is a keyword list.

So, if you want to go further and validate the given options to the Oban.Plugins.Cron plugin, for example, you need to know a bit about the internal implementation and use a combination of Oban.Plugins.Cron.validate!/1 and Oban.Plugins.Cron.init/1. Then, finally, you need to assert that the returned {:ok, state, _} is what you expect.

I like to validate the cron plugin configuration because it constantly evolves, and it's easy to catch typos in the cron worker module names also validating the cron expressions by doing the following:

assert :ok = Oban.Plugins.Cron.validate!(cron_opts)

assert {:ok, _state, {:continue, :start}} = Oban.Plugins.Cron.init(cron_opts)

But again, here I'm, relying on a function for internal use. Still, I think it is worth taking the risk of using a non-documented public function in this case; you gain more in your daily routine because it will allow you to catch errors in your Oban Configuration as soon as possible.

Describe the Solution You'd Like

A public test helper to validate the Oban configuration, including plugins. I think it's also worth normalizing the plugins under a contract or behavior; Oban now enforces defining an init/1 function for plugins, but I think the behaviour should also include a validate!/1 function. At least the validate!/1 should help with the testing experience.

There are also plugins in the Pro package that could include complex configurations, like the Oban.Pro.Plugins.DynamicPruner. So, I think it's worth it to offer a unified way to validate these configs.

Describe Alternatives You've Considered

I'm currently testing my Oban configuration using the workarounds that I mentioned previously.

Additional Context

Not that I can think of at the moment, but let me know if you need more information. I'm always happy to help :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions