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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions