Skip to content

Commit

Permalink
Add instructions for running integration tests against local DDB, mak…
Browse files Browse the repository at this point in the history
…e sure to delete test tables after running integration, version bump to 2.2.2
  • Loading branch information
darrenklein committed Sep 25, 2019
1 parent 7a1952f commit e3d6c70
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 61 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore config/test.exs to avoid unintentionally interfering with a user's local DDB instance. See README.
config/test.exs
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,39 @@ config :ex_aws, :dynamodb,
decode_sets: true
```

## Local testing

This application supports three test commands:

* `mix test` - run the normal test suite
* `mix test.options` - run the test suite with options enabled (see `config/test_options.exs`)
* `mix test.all` - run `mix test` and `mix test.options` sequentially

### Integration tests (optional)

The tests in `test/lib/dynamo/integration_test.exs` will attempt to run against a running local instance of DynamoDB - in order to run these tests, you will need both a running local instance of DynamoDB as well as a `config/test.exs` file (currently gitignored) formatted like so:

`config/test.exs`
```elixir
use Mix.Config

config :ex_aws, :dynamodb,
scheme: "http://",
host: "localhost",
port: CHOOSE_YOUR_TEST_PORT,
region: "us-east-1"

config :ex_aws,
debug_requests: true,
access_key_id: "abcd",
secret_access_key: "1234",
region: "us-east-1"
```

Before setting the `port`, be aware that `integration_test.exs` will create and delete tables with the names `"TestUsers", Test.User, "TestSeveralUsers", TestFoo, "test_books", "TestUsersWithRange"` - be careful when setting the port, as these operations may interfere with your current tables if they share any of those names.

If you do not have a running local instance of DynamoDB and/or you don't provide a `config/test.exs` file, the integration tests will hang for a few seconds before returning `invalid` - this will not interfere with the successful execution of other tests.

## License

The MIT License (MIT)
Expand Down
40 changes: 1 addition & 39 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -1,41 +1,3 @@
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
use Mix.Config

config :ex_aws, :dynamodb,
scheme: "http://",
host: "localhost",
port: 8000,
region: "us-east-1"

case Mix.env do
:test_options -> import_config "test_options.exs"
_ -> nil
end

# This configuration is loaded before any dependency and is restricted
# to this project. If another project depends on this project, this
# file won't be loaded nor affect the parent project. For this reason,
# if you want to provide default values for your application for
# 3rd-party users, it should be done in your "mix.exs" file.

# You can configure your application as:
#
# config :ex_aws_dynamo, key: :value
#
# and access this configuration in your application as:
#
# Application.get_env(:ex_aws_dynamo, :key)
#
# You can also configure a 3rd-party app:
#
# config :logger, level: :info
#

# It is also possible to import configuration files, relative to this
# directory. For example, you can emulate configuration per environment
# by uncommenting the line below and defining dev.exs, test.exs and such.
# Configuration from the imported file will override the ones defined
# here (which is why it is important to import them last).
#
# import_config "#{Mix.env}.exs"
import_config "#{Mix.env}.exs"
7 changes: 7 additions & 0 deletions config/dev.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use Mix.Config

config :ex_aws, :dynamodb,
scheme: "http://",
host: "localhost",
port: 8000,
region: "us-east-1"
2 changes: 2 additions & 0 deletions config/test_options.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ require Logger

config :ex_aws, :dynamodb,
decode_sets: true

import_config "test.exs"
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule ExAws.Dynamo.Mixfile do
use Mix.Project

@version "2.2.1"
@version "2.2.2"
@service "dynamo"
@url "https://github.com/ex-aws/ex_aws_#{@service}"
@name __MODULE__ |> Module.split() |> Enum.take(2) |> Enum.join(".")
Expand Down
43 changes: 22 additions & 21 deletions test/lib/dynamo/integration_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,27 @@ defmodule ExAws.DynamoIntegrationTest do
@moduletag :dynamo

setup_all do
Dynamo.delete_table("Users") |> ExAws.request()
Dynamo.delete_table(Test.User) |> ExAws.request()
Dynamo.delete_table("SeveralUsers") |> ExAws.request()
Dynamo.delete_table(Foo) |> ExAws.request()
Dynamo.delete_table("books") |> ExAws.request()
:ok
tables = [ "TestUsers", Test.User, "TestSeveralUsers", TestFoo, "test_books", "TestUsersWithRange" ]

DDBLocal.delete_test_tables(tables)

on_exit(fn ->
DDBLocal.delete_test_tables(tables)
end)
end

test "#list_tables" do
assert {:ok, %{"TableNames" => _}} = Dynamo.list_tables() |> ExAws.request()
end

test "#create and destroy table" do
assert {:ok, %{"TableDescription" => %{"TableName" => "Elixir.Foo"}}} =
Dynamo.create_table(Foo, :shard_id, [shard_id: :string], 1, 1) |> ExAws.request()
assert {:ok, %{"TableDescription" => %{"TableName" => "Elixir.TestFoo"}}} =
Dynamo.create_table(TestFoo, :shard_id, [shard_id: :string], 1, 1) |> ExAws.request()
end

test "#create table with range" do
assert Dynamo.create_table(
"UsersWithRange",
"TestUsersWithRange",
[email: :hash, age: :range],
[email: :string, age: :number],
1,
Expand Down Expand Up @@ -63,7 +64,7 @@ defmodule ExAws.DynamoIntegrationTest do

test "put and get several items with map values work" do
{:ok, _} =
Dynamo.create_table("SeveralUsers", :email, [email: :string], 1, 1) |> ExAws.request()
Dynamo.create_table("TestSeveralUsers", :email, [email: :string], 1, 1) |> ExAws.request()

user1 = %Test.User{
email: "foo@bar.com",
Expand All @@ -79,11 +80,11 @@ defmodule ExAws.DynamoIntegrationTest do
admin: true
}

assert {:ok, _} = Dynamo.put_item("SeveralUsers", user1) |> ExAws.request()
assert {:ok, _} = Dynamo.put_item("SeveralUsers", user2) |> ExAws.request()
assert {:ok, _} = Dynamo.put_item("TestSeveralUsers", user1) |> ExAws.request()
assert {:ok, _} = Dynamo.put_item("TestSeveralUsers", user2) |> ExAws.request()

items =
Dynamo.scan("SeveralUsers", limit: 2)
Dynamo.scan("TestSeveralUsers", limit: 2)
|> ExAws.request!()
|> Dynamo.decode_item(as: Test.User)

Expand All @@ -92,7 +93,7 @@ defmodule ExAws.DynamoIntegrationTest do
end

test "stream scan" do
{:ok, _} = Dynamo.create_table("Users", :email, [email: :string], 1, 1) |> ExAws.request()
{:ok, _} = Dynamo.create_table("TestUsers", :email, [email: :string], 1, 1) |> ExAws.request()

user = %Test.User{
email: "foo@bar.com",
Expand All @@ -101,7 +102,7 @@ defmodule ExAws.DynamoIntegrationTest do
admin: false
}

assert {:ok, _} = Dynamo.put_item("Users", user) |> ExAws.request()
assert {:ok, _} = Dynamo.put_item("TestUsers", user) |> ExAws.request()

user = %Test.User{
email: "bar@bar.com",
Expand All @@ -110,7 +111,7 @@ defmodule ExAws.DynamoIntegrationTest do
admin: false
}

assert {:ok, _} = Dynamo.put_item("Users", user) |> ExAws.request()
assert {:ok, _} = Dynamo.put_item("TestUsers", user) |> ExAws.request()

user = %Test.User{
email: "baz@bar.com",
Expand All @@ -119,17 +120,17 @@ defmodule ExAws.DynamoIntegrationTest do
admin: false
}

assert {:ok, _} = Dynamo.put_item("Users", user) |> ExAws.request()
assert {:ok, _} = Dynamo.put_item("TestUsers", user) |> ExAws.request()

assert Dynamo.scan("Users", limit: 1)
assert Dynamo.scan("TestUsers", limit: 1)
|> ExAws.stream!()
|> Enum.count() == 3
end

test "batch_write_item works" do
{:ok, _} =
Dynamo.create_table(
"books",
"test_books",
[title: "hash", format: "range"],
[title: :string, format: :string],
1,
Expand All @@ -142,13 +143,13 @@ defmodule ExAws.DynamoIntegrationTest do
[put_request: [item: %{title: "Tale of Two Cities", format: "softcover", price: 10.00}]]
]

assert {:ok, _} = Dynamo.batch_write_item(%{"books" => requests}) |> ExAws.request()
assert {:ok, _} = Dynamo.batch_write_item(%{"test_books" => requests}) |> ExAws.request()

delete_requests = [
[delete_request: [key: %{title: "Tale of Two Cities", format: "hardcover"}]],
[delete_request: [key: %{title: "Tale of Two Cities", format: "softcover"}]]
]

assert {:ok, _} = Dynamo.batch_write_item(%{"books" => delete_requests}) |> ExAws.request()
assert {:ok, _} = Dynamo.batch_write_item(%{"test_books" => delete_requests}) |> ExAws.request()
end
end
16 changes: 16 additions & 0 deletions test/support/ddb_local.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
defmodule DDBLocal do
@moduledoc """
Helper methods for working with local DynamoDB during testing.
"""

alias ExAws.Dynamo

@doc """
Delete tables created while running tests.
"""
def delete_test_tables(tables) do
tables
|> Enum.each(fn table -> Dynamo.delete_table(table) |> ExAws.request() end)
:ok
end
end

0 comments on commit e3d6c70

Please sign in to comment.