garrensmith commented on a change in pull request #2039: Exunit simplified
URL: https://github.com/apache/couchdb/pull/2039#discussion_r288429956
##########
File path: test/elixir/README.md
##########
@@ -111,3 +111,146 @@ X means done, - means partially
- [ ] Port view_pagination.js
- [ ] Port view_sandboxing.js
- [ ] Port view_update_seq.js
+
+# Using ExUnit to write unit tests
+
+Elixir has a number of benefits which makes writing unit tests easier.
+For example it is trivial to do codegeneration of tests.
+Bellow we present a few use cases where code-generation is really helpful.
+
+## How to write ExUnit tests
+
+1. Create new file in test/exunit/ directory (the file name should match
*_test.exs)
+2. In case it is a first file in the directory create test_helper.exs (look at
src/couch/test/exunit/test_helper.exs to get an idea)
+3. define test module which does `use Couch.Test.ExUnit.Case`
+4. Define test cases in the module
+
+You can run tests either:
+- using make: `make exunit`
+- using mix: BUILDDIR=`pwd` ERL_LIBS=`pwd`/src MIX_ENV=test mix test --trace
+
+## Generating tests from spec
+
+Sometimes we have some data in structured format and want
+to generate test cases using that data. This is easy in Elixir.
+For example suppose we have following spec:
+```
+{
+ "{db_name}/_view_cleanup": {
+ "roles": ["_admin"]
+ }
+}
+```
+We can use this spec to generate test cases
+```
+defmodule GenerateTestsFromSpec do
+ use ExUnit.Case
+ require Record
+ Record.defrecordp :user_ctx, Record.extract(:user_ctx, from_lib:
"couch/include/couch_db.hrl")
+ Record.defrecordp :httpd, Record.extract(:httpd, from_lib:
"couch/include/couch_db.hrl")
+
+ {:ok, spec_bin} = File.read("roles.json")
+ spec = :jiffy.decode(spec_bin, [:return_maps])
+ Enum.each spec, fn {path, path_spec} ->
+ roles = path_spec["roles"]
+ @roles roles
+ @path_parts String.split(path, "/")
+ test "Access with `#{inspect(roles)}` roles" do
+ req = httpd(path_parts: @path_parts, user_ctx: user_ctx(roles: @roles))
+ :chttpd_auth_request.authorize_request(req)
+ end
+ end
+end
+```
+As a result we would get
+```
+GenerateTestsFromSpec
+ * test Access with `["_admin"]` roles (0.00ms)
+```
+
+## Test all possible combinations
+
+Sometimes we want to test all possible permutations for parameters.
+This can be accomplished using something like the following:
+
+```
+defmodule Permutations do
+ use ExUnit.Case
+ pairs = :couch_tests_combinatorics.product([
+ [:remote, :local], [:remote, :local]
+ ])
+ for [source, dest] <- pairs do
+ @source source
+ @dest dest
+ test "Replication #{source} -> #{dest}" do
+ assert :ok == :ok
+ end
+ end
+end
+```
+
+This would produce following tests
+```
+Permutations
+ * test Replication remote -> remote (0.00ms)
+ * test Replication local -> remote (0.00ms)
+ * test Replication remote -> local (0.00ms)
+ * test Replication local -> local (0.00ms)
+```
+
+## Reuseing of common setups
+
+The setup functions are quite similar in lots of tests therefore it makes
+sense to reuse them. The idea is to add shared setup functions into either
+- test/elixir/lib/setup/common.ex
+- test/elixir/lib/setup/<something>.ex
+
+The setup functions looks like the following:
+```
+defmodule Foo do
+ alias Couch.Test.Setup.Step
+
+ def httpd_with_admin(setup) do
+ setup
+ |> Step.Start.new(:start, extra_apps: [:chttpd])
+ |> Step.User.new(:admin, roles: [:server_admin])
+ end
+end
+```
+
+These parts of a setup chain can be invoked as follows:
+```
+defmodule Couch.Test.CRUD do
+ use Couch.Test.ExUnit.Case
+ alias Couch.Test.Utils
+
+ alias Couch.Test.Setup
+
+ alias Couch.Test.Setup.Step
+
+ def with_db(context, setup) do
+ setup =
+ setup
+ |> Setup.Common.httpd_with_db()
+ |> Setup.run()
+
+ context =
+ Map.merge(context, %{
+ db_name: setup |> Setup.get(:db) |> Step.Create.DB.name(),
+ base_url: setup |> Setup.get(:start) |> Step.Start.clustered_url(),
+ user: setup |> Setup.get(:admin) |> Step.User.name()
+ })
+
+ {context, setup}
+ end
+
+ describe "Database CRUD using Fabric API" do
Review comment:
Really nice documentation, this helps a lot.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services