Skip to content

RFC for testing package design #1

@joshsmith

Description

@joshsmith

We should discuss what this should look like.

Here are some notes from beam-community/stripity-stripe#124

The test package can distribute a lightweight replica of the Stripe service. That way, testing can be done something like the following:

test "retrieves all plans where the storage limit is greater than 30" do
  Stripe.Test.create(:plan, 10)
  Stripe.Test.create(:plan, 10, metadata: [storage_limit: 10])
  Stripe.Test.create(:plan, 10, metadata: [storage_limit: 35])
  Stripe.Test.create(:plan, 10, metadata: [storage_limit: 30])

  # This is business logic that will call the StripityStripe module
  plans = MyApp.Module.get_plans(:gt, 30) 

  assert Enum.count(plans) == 10
end

The data can be stored on a per-test basis in ETS, allowing users to build up the necessary state and tear it down without needing to know the intricacies of the system.

For example:

defmodule Stripe.CustomerTest do
  # this may be able to be true
  use ExUnit.Case, async: false
  
  # Most of this setup process can be abstracted into the library, but putting
  # it here so that others understand
  setup do
    # Starts a separate process
    #   - That process loads a Plug responder that binds to an available port
    #   - It also seeds an ETS table that it claims ownership of
    #   - The ETS table and Plug responder are bound to this specific test,
    #      so they are isolated to this test and any state manipulation on them
    #      will not affect other tests
    #   - Returns a struct of some form like %Stripe.Test.Server{port: 4515, pid: #PID<0.35.0>}
    {:ok, stripe_server} = Stripe.Test.Server.start()
    
    Application.put_env(:stripity_stripe, :api_base_url, "http://localhost:#{stripe_server.port}")
    
    on_exit fn ->
       #  Cleans up the ETS table and stops the plug responder and owning process
       Stripe.Test.Server.stop(stripe_server)
    end
    
    {:ok, stripe: stripe_server}
  end

  describe "Stripe.Customer.retrieve/1" do
    test "retrieves a customer by ID", %{stripe: stripe} do
      # Uses the Stripe.Test.Customer module to create a new customer in the
      # ETS backed server (essentially, this is a factory method)
      %{id: id} = Stripe.Test.Customer.create(stripe)

      # Makes an actual API request from the high level API through the low level
      # API and through the OS network stack
      {:ok, customer} = Stripe.Customer.retrieve(id)
      
      assert customer.id == id
    end
  end
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions