You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ji...@apache.org on 2018/08/09 03:05:01 UTC

[couchdb] 06/06: Enhance PSE tests with setup/teardown functions

This is an automated email from the ASF dual-hosted git repository.

jiangphcn pushed a commit to branch COUCHDB-3326-clustered-purge-pr3-refactor-pse-tests
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 163b02ef169983c91a5e73e5363980634645db36
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Wed May 23 15:31:08 2018 -0500

    Enhance PSE tests with setup/teardown functions
---
 src/couch_pse_tests/src/cpse_gather.erl            | 95 ++++++++++++++++++++++
 src/couch_pse_tests/src/cpse_test_attachments.erl  | 15 ++--
 src/couch_pse_tests/src/cpse_test_compaction.erl   | 26 +++---
 src/couch_pse_tests/src/cpse_test_fold_changes.erl | 54 ++++++------
 src/couch_pse_tests/src/cpse_test_fold_docs.erl    | 90 ++++++++++----------
 .../src/cpse_test_get_set_props.erl                | 28 ++++---
 .../src/cpse_test_open_close_delete.erl            | 34 ++++----
 src/couch_pse_tests/src/cpse_test_purge_docs.erl   | 23 +++---
 .../src/cpse_test_read_write_docs.erl              | 49 ++++-------
 src/couch_pse_tests/src/cpse_test_ref_counting.erl | 19 +++--
 src/couch_pse_tests/src/cpse_util.erl              | 52 ++++--------
 11 files changed, 290 insertions(+), 195 deletions(-)

diff --git a/src/couch_pse_tests/src/cpse_gather.erl b/src/couch_pse_tests/src/cpse_gather.erl
new file mode 100644
index 0000000..7804d41
--- /dev/null
+++ b/src/couch_pse_tests/src/cpse_gather.erl
@@ -0,0 +1,95 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+%   http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(cpse_gather).
+
+
+-export([
+    module/1
+]).
+
+
+module(ModName) ->
+    Exports = ModName:module_info(exports),
+
+    SetupMod = get_setup_all(ModName, Exports),
+    TeardownMod = get_teardown_all(ModName, Exports),
+    SetupTest = get_fun(ModName, setup_each, 0, Exports),
+    TeardownTest = get_fun(ModName, teardown_each, 1, Exports),
+
+    RevTests = lists:foldl(fun({Fun, Arity}, Acc) ->
+        case {atom_to_list(Fun), Arity} of
+            {[$c, $p, $s, $e, $_ | _], Arity} when Arity == 0; Arity == 1 ->
+                TestFun = make_test_fun(ModName, Fun, Arity),
+                [TestFun | Acc];
+            _ ->
+                Acc
+        end
+    end, [], Exports),
+    Tests = lists:reverse(RevTests),
+
+    {
+        setup,
+        spawn,
+        SetupMod,
+        TeardownMod,
+        [
+            {
+                foreach,
+                SetupTest,
+                TeardownTest,
+                Tests
+            }
+        ]
+    }.
+
+
+get_setup_all(ModName, Exports) ->
+    case lists:member({setup_all, 0}, Exports) of
+        true -> fun ModName:setup_all/0;
+        false -> fun cpse_util:setup_all/0
+    end.
+
+
+get_teardown_all(ModName, Exports) ->
+    case lists:member({teardown_all, 1}, Exports) of
+        true -> fun ModName:teardown_all/1;
+        false -> fun cpse_util:teardown_all/1
+    end.
+
+
+get_fun(ModName, FunName, Arity, Exports) ->
+    case lists:member({FunName, Arity}, Exports) of
+        true -> fun ModName:FunName/Arity;
+        false when Arity == 0 -> fun() -> ok end;
+        false when Arity == 1 -> fun(_) -> ok end
+    end.
+
+
+make_test_fun(Module, Fun, Arity) ->
+    Name = atom_to_list(Fun),
+    case Arity of
+        0 ->
+            fun(_) ->
+                {timeout, 60, {Name, fun() ->
+                    process_flag(trap_exit, true),
+                    Module:Fun()
+                end}}
+            end;
+        1 ->
+            fun(Arg) ->
+                {timeout, 60, {Name, fun() ->
+                    process_flag(trap_exit, true),
+                    Module:Fun(Arg)
+                end}}
+            end
+    end.
diff --git a/src/couch_pse_tests/src/cpse_test_attachments.erl b/src/couch_pse_tests/src/cpse_test_attachments.erl
index 7372ba4..61ada38 100644
--- a/src/couch_pse_tests/src/cpse_test_attachments.erl
+++ b/src/couch_pse_tests/src/cpse_test_attachments.erl
@@ -18,9 +18,16 @@
 -include_lib("couch/include/couch_db.hrl").
 
 
-cet_write_attachment() ->
-    {ok, Db1} = cpse_util:create_db(),
+setup_each() ->
+    {ok, Db} = cpse_util:create_db(),
+    Db.
 
+
+teardown_each(Db) ->
+    ok = couch_server:delete(couch_db:name(Db), []).
+
+
+cpse_write_attachment(Db1) ->
     AttBin = crypto:strong_rand_bytes(32768),
 
     try
@@ -72,9 +79,7 @@ cet_write_attachment() ->
 % attachments streams when restarting (for instance if
 % we ever have something that stores attachemnts in
 % an external object store)
-cet_inactive_stream() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_inactive_stream(Db1) ->
     AttBin = crypto:strong_rand_bytes(32768),
 
     try
diff --git a/src/couch_pse_tests/src/cpse_test_compaction.erl b/src/couch_pse_tests/src/cpse_test_compaction.erl
index 122feba..11bf106 100644
--- a/src/couch_pse_tests/src/cpse_test_compaction.erl
+++ b/src/couch_pse_tests/src/cpse_test_compaction.erl
@@ -18,8 +18,16 @@
 -include_lib("couch/include/couch_db.hrl").
 
 
-cet_compact_empty() ->
-    {ok, Db1} = cpse_util:create_db(),
+setup_each() ->
+    {ok, Db} = cpse_util:create_db(),
+    Db.
+
+
+teardown_each(Db) ->
+    ok = couch_server:delete(couch_db:name(Db), []).
+
+
+cpse_compact_empty(Db1) ->
     Term1 = cpse_util:db_as_term(Db1),
 
     cpse_util:compact(Db1),
@@ -31,8 +39,7 @@ cet_compact_empty() ->
     ?assertEqual(nodiff, Diff).
 
 
-cet_compact_doc() ->
-    {ok, Db1} = cpse_util:create_db(),
+cpse_compact_doc(Db1) ->
     Actions = [{create, {<<"foo">>, {[]}}}],
     {ok, Db2} = cpse_util:apply_actions(Db1, Actions),
     Term1 = cpse_util:db_as_term(Db2),
@@ -46,8 +53,7 @@ cet_compact_doc() ->
     ?assertEqual(nodiff, Diff).
 
 
-cet_compact_local_doc() ->
-    {ok, Db1} = cpse_util:create_db(),
+cpse_compact_local_doc(Db1) ->
     Actions = [{create, {<<"_local/foo">>, {[]}}}],
     {ok, Db2} = cpse_util:apply_actions(Db1, Actions),
     Term1 = cpse_util:db_as_term(Db2),
@@ -61,9 +67,7 @@ cet_compact_local_doc() ->
     ?assertEqual(nodiff, Diff).
 
 
-cet_compact_with_everything() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_compact_with_everything(Db1) ->
     % Add a whole bunch of docs
     DocActions = lists:map(fun(Seq) ->
         {create, {docid(Seq), {[{<<"int">>, Seq}]}}}
@@ -150,9 +154,7 @@ cet_compact_with_everything() ->
     ?assertEqual(nodiff, Diff).
 
 
-cet_recompact_updates() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_recompact_updates(Db1) ->
     Actions1 = lists:map(fun(Seq) ->
         {create, {docid(Seq), {[{<<"int">>, Seq}]}}}
     end, lists:seq(1, 1000)),
diff --git a/src/couch_pse_tests/src/cpse_test_fold_changes.erl b/src/couch_pse_tests/src/cpse_test_fold_changes.erl
index 64ae34d..8ee74f0 100644
--- a/src/couch_pse_tests/src/cpse_test_fold_changes.erl
+++ b/src/couch_pse_tests/src/cpse_test_fold_changes.erl
@@ -21,15 +21,22 @@
 -define(NUM_DOCS, 25).
 
 
-cet_empty_changes() ->
+setup_each() ->
     {ok, Db} = cpse_util:create_db(),
+    Db.
+
+
+teardown_each(Db) ->
+    ok = couch_server:delete(couch_db:name(Db), []).
+
+
+cpse_empty_changes(Db) ->
     ?assertEqual(0, couch_db_engine:count_changes_since(Db, 0)),
     ?assertEqual({ok, []},
             couch_db_engine:fold_changes(Db, 0, fun fold_fun/2, [], [])).
 
 
-cet_single_change() ->
-    {ok, Db1} = cpse_util:create_db(),
+cpse_single_change(Db1) ->
     Actions = [{create, {<<"a">>, {[]}}}],
     {ok, Db2} = cpse_util:apply_actions(Db1, Actions),
 
@@ -38,8 +45,7 @@ cet_single_change() ->
             couch_db_engine:fold_changes(Db2, 0, fun fold_fun/2, [], [])).
 
 
-cet_two_changes() ->
-    {ok, Db1} = cpse_util:create_db(),
+cpse_two_changes(Db1) ->
     Actions = [
         {create, {<<"a">>, {[]}}},
         {create, {<<"b">>, {[]}}}
@@ -52,38 +58,37 @@ cet_two_changes() ->
     ?assertEqual([{<<"a">>, 1}, {<<"b">>, 2}], lists:reverse(Changes)).
 
 
-cet_two_changes_batch() ->
-    {ok, Db1} = cpse_util:create_db(),
-    Actions1 = [
+cpse_two_changes_batch(Db1) ->
+    Actions = [
         {batch, [
             {create, {<<"a">>, {[]}}},
             {create, {<<"b">>, {[]}}}
         ]}
     ],
-    {ok, Db2} = cpse_util:apply_actions(Db1, Actions1),
+    {ok, Db2} = cpse_util:apply_actions(Db1, Actions),
 
     ?assertEqual(2, couch_db_engine:count_changes_since(Db2, 0)),
-    {ok, Changes1} =
+    {ok, Changes} =
             couch_db_engine:fold_changes(Db2, 0, fun fold_fun/2, [], []),
-    ?assertEqual([{<<"a">>, 1}, {<<"b">>, 2}], lists:reverse(Changes1)),
+    ?assertEqual([{<<"a">>, 1}, {<<"b">>, 2}], lists:reverse(Changes)).
 
-    {ok, Db3} = cpse_util:create_db(),
-    Actions2 = [
+
+cpse_two_changes_batch_sorted(Db1) ->
+    Actions = [
         {batch, [
             {create, {<<"b">>, {[]}}},
             {create, {<<"a">>, {[]}}}
         ]}
     ],
-    {ok, Db4} = cpse_util:apply_actions(Db3, Actions2),
+    {ok, Db2} = cpse_util:apply_actions(Db1, Actions),
 
-    ?assertEqual(2, couch_db_engine:count_changes_since(Db4, 0)),
-    {ok, Changes2} =
-            couch_db_engine:fold_changes(Db4, 0, fun fold_fun/2, [], []),
-    ?assertEqual([{<<"a">>, 1}, {<<"b">>, 2}], lists:reverse(Changes2)).
+    ?assertEqual(2, couch_db_engine:count_changes_since(Db2, 0)),
+    {ok, Changes} =
+            couch_db_engine:fold_changes(Db2, 0, fun fold_fun/2, [], []),
+    ?assertEqual([{<<"a">>, 1}, {<<"b">>, 2}], lists:reverse(Changes)).
 
 
-cet_update_one() ->
-    {ok, Db1} = cpse_util:create_db(),
+cpse_update_one(Db1) ->
     Actions = [
         {create, {<<"a">>, {[]}}},
         {update, {<<"a">>, {[]}}}
@@ -95,8 +100,7 @@ cet_update_one() ->
             couch_db_engine:fold_changes(Db2, 0, fun fold_fun/2, [], [])).
 
 
-cet_update_first_of_two() ->
-    {ok, Db1} = cpse_util:create_db(),
+cpse_update_first_of_two(Db1) ->
     Actions = [
         {create, {<<"a">>, {[]}}},
         {create, {<<"b">>, {[]}}},
@@ -110,8 +114,7 @@ cet_update_first_of_two() ->
     ?assertEqual([{<<"b">>, 2}, {<<"a">>, 3}], lists:reverse(Changes)).
 
 
-cet_update_second_of_two() ->
-    {ok, Db1} = cpse_util:create_db(),
+cpse_update_second_of_two(Db1) ->
     Actions = [
         {create, {<<"a">>, {[]}}},
         {create, {<<"b">>, {[]}}},
@@ -125,7 +128,7 @@ cet_update_second_of_two() ->
     ?assertEqual([{<<"a">>, 1}, {<<"b">>, 3}], lists:reverse(Changes)).
 
 
-cet_check_mutation_ordering() ->
+cpse_check_mutation_ordering(Db1) ->
     Actions = shuffle(lists:map(fun(Seq) ->
         {create, {docid(Seq), {[]}}}
     end, lists:seq(1, ?NUM_DOCS))),
@@ -133,7 +136,6 @@ cet_check_mutation_ordering() ->
     DocIdOrder = [DocId || {_, {DocId, _}} <- Actions],
     DocSeqs = lists:zip(DocIdOrder, lists:seq(1, ?NUM_DOCS)),
 
-    {ok, Db1} = cpse_util:create_db(),
     {ok, Db2} = cpse_util:apply_actions(Db1, Actions),
 
     % First lets see that we can get the correct
diff --git a/src/couch_pse_tests/src/cpse_test_fold_docs.erl b/src/couch_pse_tests/src/cpse_test_fold_docs.erl
index d9345fe..09fbd26 100644
--- a/src/couch_pse_tests/src/cpse_test_fold_docs.erl
+++ b/src/couch_pse_tests/src/cpse_test_fold_docs.erl
@@ -21,59 +21,67 @@
 -define(NUM_DOCS, 100).
 
 
-cet_fold_all() ->
-    fold_all(fold_docs, fun docid/1).
+setup_each() ->
+    cpse_util:dbname().
 
 
-cet_fold_all_local() ->
-    fold_all(fold_local_docs, fun local_docid/1).
+teardown_each(DbName) ->
+    ok = couch_server:delete(DbName, []).
 
 
-cet_fold_start_key() ->
-    fold_start_key(fold_docs, fun docid/1).
+cpse_fold_all(DbName) ->
+    fold_all(DbName, fold_docs, fun docid/1).
 
 
-cet_fold_start_key_local() ->
-    fold_start_key(fold_local_docs, fun local_docid/1).
+cpse_fold_all_local(DbName) ->
+    fold_all(DbName, fold_local_docs, fun local_docid/1).
 
 
-cet_fold_end_key() ->
-    fold_end_key(fold_docs, fun docid/1).
+cpse_fold_start_key(DbName) ->
+    fold_start_key(DbName, fold_docs, fun docid/1).
 
 
-cet_fold_end_key_local() ->
-    fold_end_key(fold_local_docs, fun local_docid/1).
+cpse_fold_start_key_local(DbName) ->
+    fold_start_key(DbName, fold_local_docs, fun local_docid/1).
 
 
-cet_fold_end_key_gt() ->
-    fold_end_key_gt(fold_docs, fun docid/1).
+cpse_fold_end_key(DbName) ->
+    fold_end_key(DbName, fold_docs, fun docid/1).
 
 
-cet_fold_end_key_gt_local() ->
-    fold_end_key_gt(fold_local_docs, fun local_docid/1).
+cpse_fold_end_key_local(DbName) ->
+    fold_end_key(DbName, fold_local_docs, fun local_docid/1).
 
 
-cet_fold_range() ->
-    fold_range(fold_docs, fun docid/1).
+cpse_fold_end_key_gt(DbName) ->
+    fold_end_key_gt(DbName, fold_docs, fun docid/1).
 
 
-cet_fold_range_local() ->
-    fold_range(fold_local_docs, fun local_docid/1).
+cpse_fold_end_key_gt_local(DbName) ->
+    fold_end_key_gt(DbName, fold_local_docs, fun local_docid/1).
 
 
-cet_fold_stop() ->
-    fold_user_fun_stop(fold_docs, fun docid/1).
+cpse_fold_range(DbName) ->
+    fold_range(DbName, fold_docs, fun docid/1).
 
 
-cet_fold_stop_local() ->
-    fold_user_fun_stop(fold_local_docs, fun local_docid/1).
+cpse_fold_range_local(DbName) ->
+    fold_range(DbName, fold_local_docs, fun local_docid/1).
+
+
+cpse_fold_stop(DbName) ->
+    fold_user_fun_stop(DbName, fold_docs, fun docid/1).
+
+
+cpse_fold_stop_local(DbName) ->
+    fold_user_fun_stop(DbName, fold_local_docs, fun local_docid/1).
 
 
 % This is a loose test but we have to have this until
 % I figure out what to do about the total_rows/offset
 % meta data included in _all_docs
-cet_fold_include_reductions() ->
-    {ok, Db} = init_st(fun docid/1),
+cpse_fold_include_reductions(DbName) ->
+    {ok, Db} = init_db(DbName, fun docid/1),
     FoldFun = fun(_, _, nil) -> {ok, nil} end,
     Opts = [include_reductions],
     {ok, Count, nil} = couch_db_engine:fold_docs(Db, FoldFun, nil, Opts),
@@ -81,9 +89,9 @@ cet_fold_include_reductions() ->
     ?assert(Count >= 0).
 
 
-fold_all(FoldFun, DocIdFun) ->
+fold_all(DbName, FoldFun, DocIdFun) ->
     DocIds = [DocIdFun(I) || I <- lists:seq(1, ?NUM_DOCS)],
-    {ok, Db} = init_st(DocIdFun),
+    {ok, Db} = init_db(DbName, DocIdFun),
 
     {ok, DocIdAccFwd} = couch_db_engine:FoldFun(Db, fun fold_fun/2, [], []),
     ?assertEqual(?NUM_DOCS, length(DocIdAccFwd)),
@@ -95,8 +103,8 @@ fold_all(FoldFun, DocIdFun) ->
     ?assertEqual(DocIds, DocIdAccRev).
 
 
-fold_start_key(FoldFun, DocIdFun) ->
-    {ok, Db} = init_st(DocIdFun),
+fold_start_key(DbName, FoldFun, DocIdFun) ->
+    {ok, Db} = init_db(DbName, DocIdFun),
 
     StartKeyNum = ?NUM_DOCS div 4,
     StartKey = DocIdFun(StartKeyNum),
@@ -141,8 +149,8 @@ fold_start_key(FoldFun, DocIdFun) ->
     ?assertEqual(DocIdsRev, DocIdAccRev).
 
 
-fold_end_key(FoldFun, DocIdFun) ->
-    {ok, Db} = init_st(DocIdFun),
+fold_end_key(DbName, FoldFun, DocIdFun) ->
+    {ok, Db} = init_db(DbName, DocIdFun),
 
     EndKeyNum = ?NUM_DOCS div 4,
     EndKey = DocIdFun(EndKeyNum),
@@ -189,8 +197,8 @@ fold_end_key(FoldFun, DocIdFun) ->
     ?assertEqual(DocIdsRev, DocIdAccRev).
 
 
-fold_end_key_gt(FoldFun, DocIdFun) ->
-    {ok, Db} = init_st(DocIdFun),
+fold_end_key_gt(DbName, FoldFun, DocIdFun) ->
+    {ok, Db} = init_db(DbName, DocIdFun),
 
     EndKeyNum = ?NUM_DOCS div 4,
     EndKey = DocIdFun(EndKeyNum),
@@ -237,8 +245,8 @@ fold_end_key_gt(FoldFun, DocIdFun) ->
     ?assertEqual(DocIdsRev, DocIdAccRev).
 
 
-fold_range(FoldFun, DocIdFun) ->
-    {ok, Db} = init_st(DocIdFun),
+fold_range(DbName, FoldFun, DocIdFun) ->
+    {ok, Db} = init_db(DbName, DocIdFun),
 
     StartKeyNum = ?NUM_DOCS div 4,
     EndKeyNum = StartKeyNum * 3,
@@ -300,8 +308,8 @@ fold_range(FoldFun, DocIdFun) ->
     ?assertEqual(DocIdsRev, DocIdAccRev).
 
 
-fold_user_fun_stop(FoldFun, DocIdFun) ->
-    {ok, Db} = init_st(DocIdFun),
+fold_user_fun_stop(DbName, FoldFun, DocIdFun) ->
+    {ok, Db} = init_db(DbName, DocIdFun),
 
     StartKeyNum = ?NUM_DOCS div 4,
     StartKey = DocIdFun(StartKeyNum),
@@ -352,12 +360,12 @@ fold_user_fun_stop(FoldFun, DocIdFun) ->
     ?assertEqual(FiveDocIdsRev, FiveDocIdAccRev).
 
 
-init_st(DocIdFun) ->
-    {ok, Db1} = cpse_util:create_db(),
+init_db(DbName, DocIdFun) ->
+    {ok, Db1} = cpse_util:create_db(DbName),
     Actions = lists:map(fun(Id) ->
         {create, {DocIdFun(Id), {[{<<"int">>, Id}]}}}
     end, lists:seq(1, ?NUM_DOCS)),
-    cpse_util:apply_batch(Db1, Actions).
+    cpse_util:apply_actions(Db1, [{batch, Actions}]).
 
 
 fold_fun(Doc, Acc) ->
diff --git a/src/couch_pse_tests/src/cpse_test_get_set_props.erl b/src/couch_pse_tests/src/cpse_test_get_set_props.erl
index e11f760..97f164b 100644
--- a/src/couch_pse_tests/src/cpse_test_get_set_props.erl
+++ b/src/couch_pse_tests/src/cpse_test_get_set_props.erl
@@ -17,9 +17,17 @@
 -include_lib("eunit/include/eunit.hrl").
 
 
-cet_default_props() ->
+setup_each() ->
+    cpse_util:dbname().
+
+
+teardown_each(DbName) ->
+    ok = couch_server:delete(DbName, []).
+
+
+cpse_default_props(DbName) ->
     {ok, {_App, Engine, _Extension}} = application:get_env(couch, test_engine),
-    {ok, Db} = cpse_util:create_db(),
+    {ok, Db} = cpse_util:create_db(DbName),
     Node = node(),
 
     ?assertEqual(Engine, couch_db_engine:get_engine(Db)),
@@ -47,10 +55,10 @@ cet_default_props() ->
 ]}).
 
 
-cet_admin_only_security() ->
+cpse_admin_only_security(DbName) ->
     Config = [{"couchdb", "default_security", "admin_only"}],
     {ok, Db1} = cpse_util:with_config(Config, fun() ->
-        cpse_util:create_db()
+        cpse_util:create_db(DbName)
     end),
 
     ?assertEqual(?ADMIN_ONLY_SEC_PROPS, couch_db:get_security(Db1)),
@@ -61,17 +69,17 @@ cet_admin_only_security() ->
     ?assertEqual(?ADMIN_ONLY_SEC_PROPS, couch_db:get_security(Db2)).
 
 
-cet_set_security() ->
+cpse_set_security(DbName) ->
     SecProps = {[{<<"foo">>, <<"bar">>}]},
-    check_prop_set(get_security, set_security, {[]}, SecProps).
+    check_prop_set(DbName, get_security, set_security, {[]}, SecProps).
 
 
-cet_set_revs_limit() ->
-    check_prop_set(get_revs_limit, set_revs_limit, 1000, 50).
+cpse_set_revs_limit(DbName) ->
+    check_prop_set(DbName, get_revs_limit, set_revs_limit, 1000, 50).
 
 
-check_prop_set(GetFun, SetFun, Default, Value) ->
-    {ok, Db0} = cpse_util:create_db(),
+check_prop_set(DbName, GetFun, SetFun, Default, Value) ->
+    {ok, Db0} = cpse_util:create_db(DbName),
 
     ?assertEqual(Default, couch_db:GetFun(Db0)),
     ?assertMatch(ok, couch_db:SetFun(Db0, Value)),
diff --git a/src/couch_pse_tests/src/cpse_test_open_close_delete.erl b/src/couch_pse_tests/src/cpse_test_open_close_delete.erl
index 86fa339..c19d0ee 100644
--- a/src/couch_pse_tests/src/cpse_test_open_close_delete.erl
+++ b/src/couch_pse_tests/src/cpse_test_open_close_delete.erl
@@ -17,53 +17,53 @@
 -include_lib("eunit/include/eunit.hrl").
 
 
-cet_open_non_existent() ->
+setup_each() ->
+    cpse_util:dbname().
+
+
+teardown_each(DbName) ->
+    case couch_server:exists(DbName) of
+        true -> ok = couch_server:delete(DbName, []);
+        false -> ok
+    end.
+
+
+cpse_open_non_existent(DbName) ->
     % Try twice to check that a failed open doesn't create
     % the database for some reason.
-    DbName = cpse_util:dbname(),
     ?assertEqual({not_found, no_db_file}, cpse_util:open_db(DbName)),
     ?assertEqual({not_found, no_db_file}, cpse_util:open_db(DbName)).
 
 
-cet_open_create() ->
-    DbName = cpse_util:dbname(),
-
+cpse_open_create(DbName) ->
     ?assertEqual(false, couch_server:exists(DbName)),
     ?assertEqual({not_found, no_db_file}, cpse_util:open_db(DbName)),
     ?assertMatch({ok, _}, cpse_util:create_db(DbName)),
     ?assertEqual(true, couch_server:exists(DbName)).
 
 
-cet_open_when_exists() ->
-    DbName = cpse_util:dbname(),
-
+cpse_open_when_exists(DbName) ->
     ?assertEqual(false, couch_server:exists(DbName)),
     ?assertEqual({not_found, no_db_file}, cpse_util:open_db(DbName)),
     ?assertMatch({ok, _}, cpse_util:create_db(DbName)),
     ?assertEqual(file_exists, cpse_util:create_db(DbName)).
 
 
-cet_terminate() ->
-    DbName = cpse_util:dbname(),
-
+cpse_terminate(DbName) ->
     ?assertEqual(false, couch_server:exists(DbName)),
     ?assertEqual({not_found, no_db_file}, cpse_util:open_db(DbName)),
     ?assertEqual(ok, cycle_db(DbName, create_db)),
     ?assertEqual(true, couch_server:exists(DbName)).
 
 
-cet_rapid_recycle() ->
-    DbName = cpse_util:dbname(),
-
+cpse_rapid_recycle(DbName) ->
     ?assertEqual(ok, cycle_db(DbName, create_db)),
     lists:foreach(fun(_) ->
         ?assertEqual(ok, cycle_db(DbName, open_db))
     end, lists:seq(1, 100)).
 
 
-cet_delete() ->
-    DbName = cpse_util:dbname(),
-
+cpse_delete(DbName) ->
     ?assertEqual(false, couch_server:exists(DbName)),
     ?assertMatch(ok, cycle_db(DbName, create_db)),
     ?assertEqual(true, couch_server:exists(DbName)),
diff --git a/src/couch_pse_tests/src/cpse_test_purge_docs.erl b/src/couch_pse_tests/src/cpse_test_purge_docs.erl
index 19303c2..4352268 100644
--- a/src/couch_pse_tests/src/cpse_test_purge_docs.erl
+++ b/src/couch_pse_tests/src/cpse_test_purge_docs.erl
@@ -18,9 +18,16 @@
 -include_lib("couch/include/couch_db.hrl").
 
 
-cet_purge_simple() ->
-    {ok, Db1} = cpse_util:create_db(),
+setup_each() ->
+    {ok, Db} = cpse_util:create_db(),
+    Db.
 
+
+teardown_each(Db) ->
+    ok = couch_server:delete(couch_db:name(Db), []).
+
+
+cpse_purge_simple(Db1) ->
     Actions1 = [
         {create, {<<"foo">>, {[{<<"vsn">>, 1}]}}}
     ],
@@ -48,9 +55,7 @@ cet_purge_simple() ->
     ?assertEqual([{<<"foo">>, [Rev]}], couch_db_engine:get_last_purged(Db3)).
 
 
-cet_purge_conflicts() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_purge_conflicts(Db1) ->
     Actions1 = [
         {create, {<<"foo">>, {[{<<"vsn">>, 1}]}}},
         {conflict, {<<"foo">>, {[{<<"vsn">>, 2}]}}}
@@ -94,9 +99,7 @@ cet_purge_conflicts() ->
     ?assertEqual([{<<"foo">>, [Rev2]}], couch_db_engine:get_last_purged(Db4)).
 
 
-cet_add_delete_purge() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_add_delete_purge(Db1) ->
     Actions1 = [
         {create, {<<"foo">>, {[{<<"vsn">>, 1}]}}},
         {delete, {<<"foo">>, {[{<<"vsn">>, 2}]}}}
@@ -126,9 +129,7 @@ cet_add_delete_purge() ->
     ?assertEqual([{<<"foo">>, [Rev]}], couch_db_engine:get_last_purged(Db3)).
 
 
-cet_add_two_purge_one() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_add_two_purge_one(Db1) ->
     Actions1 = [
         {create, {<<"foo">>, {[{<<"vsn">>, 1}]}}},
         {create, {<<"bar">>, {[]}}}
diff --git a/src/couch_pse_tests/src/cpse_test_read_write_docs.erl b/src/couch_pse_tests/src/cpse_test_read_write_docs.erl
index 907f5d9..84bf9f3 100644
--- a/src/couch_pse_tests/src/cpse_test_read_write_docs.erl
+++ b/src/couch_pse_tests/src/cpse_test_read_write_docs.erl
@@ -18,9 +18,16 @@
 -include_lib("couch/include/couch_db.hrl").
 
 
-cet_read_empty_docs() ->
+setup_each() ->
     {ok, Db} = cpse_util:create_db(),
+    Db.
 
+
+teardown_each(Db) ->
+    ok = couch_server:delete(couch_db:name(Db), []).
+
+
+cpse_read_docs_from_empty_db(Db) ->
     ?assertEqual([not_found], couch_db_engine:open_docs(Db, [<<"foo">>])),
     ?assertEqual(
         [not_found, not_found],
@@ -28,9 +35,7 @@ cet_read_empty_docs() ->
     ).
 
 
-cet_read_empty_local_docs() ->
-    {ok, Db} = cpse_util:create_db(),
-
+cpse_read_empty_local_docs(Db) ->
     {LocalA, LocalB} = {<<"_local/a">>, <<"_local/b">>},
     ?assertEqual([not_found], couch_db_engine:open_local_docs(Db, [LocalA])),
     ?assertEqual(
@@ -39,9 +44,7 @@ cet_read_empty_local_docs() ->
     ).
 
 
-cet_write_one_doc() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_write_one_doc(Db1) ->
     ?assertEqual(0, couch_db_engine:get_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_del_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_update_seq(Db1)),
@@ -82,9 +85,7 @@ cet_write_one_doc() ->
     ?assertEqual({[{<<"vsn">>, 1}]}, Body1).
 
 
-cet_write_two_docs() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_write_two_docs(Db1) ->
     ?assertEqual(0, couch_db_engine:get_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_del_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_update_seq(Db1)),
@@ -107,9 +108,7 @@ cet_write_two_docs() ->
     ?assertEqual(false, lists:member(not_found, Resps)).
 
 
-cet_write_three_doc_batch() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_write_three_doc_batch(Db1) ->
     ?assertEqual(0, couch_db_engine:get_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_del_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_update_seq(Db1)),
@@ -135,9 +134,7 @@ cet_write_three_doc_batch() ->
     ?assertEqual(false, lists:member(not_found, Resps)).
 
 
-cet_update_doc() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_update_doc(Db1) ->
     ?assertEqual(0, couch_db_engine:get_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_del_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_update_seq(Db1)),
@@ -179,9 +176,7 @@ cet_update_doc() ->
     ?assertEqual({[{<<"vsn">>, 2}]}, Body1).
 
 
-cet_delete_doc() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_delete_doc(Db1) ->
     ?assertEqual(0, couch_db_engine:get_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_del_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_update_seq(Db1)),
@@ -222,9 +217,7 @@ cet_delete_doc() ->
     ?assertEqual({[]}, Body1).
 
 
-cet_write_local_doc() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_write_local_doc(Db1) ->
     ?assertEqual(0, couch_db_engine:get_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_del_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_update_seq(Db1)),
@@ -247,9 +240,7 @@ cet_write_local_doc() ->
     ?assertEqual({[{<<"yay">>, false}]}, Doc#doc.body).
 
 
-cet_write_mixed_batch() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_write_mixed_batch(Db1) ->
     ?assertEqual(0, couch_db_engine:get_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_del_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_update_seq(Db1)),
@@ -277,9 +268,7 @@ cet_write_mixed_batch() ->
     [#doc{}] = couch_db_engine:open_local_docs(Db3, [<<"_local/foo">>]).
 
 
-cet_update_local_doc() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_update_local_doc(Db1) ->
     ?assertEqual(0, couch_db_engine:get_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_del_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_update_seq(Db1)),
@@ -303,9 +292,7 @@ cet_update_local_doc() ->
     ?assertEqual({[{<<"stuff">>, null}]}, Doc#doc.body).
 
 
-cet_delete_local_doc() ->
-    {ok, Db1} = cpse_util:create_db(),
-
+cpse_delete_local_doc(Db1) ->
     ?assertEqual(0, couch_db_engine:get_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_del_doc_count(Db1)),
     ?assertEqual(0, couch_db_engine:get_update_seq(Db1)),
diff --git a/src/couch_pse_tests/src/cpse_test_ref_counting.erl b/src/couch_pse_tests/src/cpse_test_ref_counting.erl
index 5529049..2a0e4c2 100644
--- a/src/couch_pse_tests/src/cpse_test_ref_counting.erl
+++ b/src/couch_pse_tests/src/cpse_test_ref_counting.erl
@@ -21,21 +21,27 @@
 -define(NUM_CLIENTS, 1000).
 
 
-cet_empty_monitors() ->
+setup_each() ->
     {ok, Db} = cpse_util:create_db(),
+    {Db, self()}.
+
+
+teardown_each({Db, _}) ->
+    ok = couch_server:delete(couch_db:name(Db), []).
+
+
+cpse_empty_monitors({Db, Pid}) ->
     Pids = couch_db_engine:monitored_by(Db),
     ?assert(is_list(Pids)),
     Expected = [
-        self(),
+        Pid,
         couch_db:get_pid(Db),
         whereis(couch_stats_process_tracker)
     ],
     ?assertEqual([], Pids -- Expected).
 
 
-cet_incref_decref() ->
-    {ok, Db} = cpse_util:create_db(),
-
+cpse_incref_decref({Db, _}) ->
     {Pid, _} = Client = start_client(Db),
     wait_client(Client),
 
@@ -48,8 +54,7 @@ cet_incref_decref() ->
     ?assert(not lists:member(Pid, Pids2)).
 
 
-cet_incref_decref_many() ->
-    {ok, Db} = cpse_util:create_db(),
+cpse_incref_decref_many({Db, _}) ->
     Clients = lists:map(fun(_) ->
         start_client(Db)
     end, lists:seq(1, ?NUM_CLIENTS)),
diff --git a/src/couch_pse_tests/src/cpse_util.erl b/src/couch_pse_tests/src/cpse_util.erl
index 2e6ba9c..202b11e 100644
--- a/src/couch_pse_tests/src/cpse_util.erl
+++ b/src/couch_pse_tests/src/cpse_util.erl
@@ -14,6 +14,7 @@
 -compile(export_all).
 
 
+-include_lib("eunit/include/eunit.hrl").
 -include_lib("couch/include/couch_db.hrl").
 
 
@@ -43,45 +44,26 @@ create_tests(EngineApp, Extension) ->
 create_tests(EngineApp, EngineModule, Extension) ->
     TestEngine = {EngineApp, EngineModule, Extension},
     application:set_env(couch, test_engine, TestEngine),
-    Tests = lists:map(fun(TestMod) ->
-        {atom_to_list(TestMod), gather(TestMod)}
-    end, ?TEST_MODULES),
-    Setup = fun() ->
-        Ctx = test_util:start_couch(),
-        EngineModStr = atom_to_list(EngineModule),
-        config:set("couchdb_engines", Extension, EngineModStr, false),
-        config:set("log", "include_sasl", "false", false),
-        Ctx
-    end,
-    {
-        setup,
-        Setup,
-        fun test_util:stop_couch/1,
-        fun(_) -> Tests end
-    }.
+    lists:map(fun(TestMod) ->
+        {atom_to_list(TestMod), cpse_gather:module(TestMod)}
+    end, ?TEST_MODULES).
 
 
-gather(Module) ->
-    Exports = Module:module_info(exports),
-    Tests = lists:foldl(fun({Fun, Arity}, Acc) ->
-        case {atom_to_list(Fun), Arity} of
-            {[$c, $e, $t, $_ | _], 0} ->
-                TestFun = make_test_fun(Module, Fun),
-                [{timeout, 60, {spawn, TestFun}} | Acc];
-            _ ->
-                Acc
-        end
-    end, [], Exports),
-    lists:reverse(Tests).
+setup_all() ->
+    setup_all([]).
 
 
-make_test_fun(Module, Fun) ->
-    Name = lists:flatten(io_lib:format("~s:~s", [Module, Fun])),
-    Wrapper = fun() ->
-        process_flag(trap_exit, true),
-        Module:Fun()
-    end,
-    {Name, Wrapper}.
+setup_all(ExtraApps) ->
+    Ctx = test_util:start_couch(ExtraApps),
+    {ok, {_, EngineMod, Extension}} = application:get_env(couch, test_engine),
+    EngineModStr = atom_to_list(EngineMod),
+    config:set("couchdb_engines", Extension, EngineModStr, false),
+    config:set("log", "include_sasl", "false", false),
+    Ctx.
+
+
+teardown_all(Ctx) ->
+    test_util:stop_couch(Ctx).
 
 
 rootdir() ->