changeset 492:173c52d3120b

Tests: create js_test fixture, closes #688 Create a js_test fixture class which generates a fake javascript plugin and loads appropriate javascript modules to test.
author David Demelier <markand@malikania.fr>
date Wed, 27 Sep 2017 09:42:57 +0200
parents 7f2ebbb7a45d
children 69e24ce9baed
files libirccd-test/CMakeLists.txt libirccd-test/irccd/js_test.hpp libirccd-test/irccd/plugin_test.js tests/js-elapsedtimer/main.cpp tests/js-file/main.cpp tests/js-irccd/main.cpp tests/js-system/main.cpp tests/js-timer/main.cpp tests/js-unicode/main.cpp tests/js-util/main.cpp
diffstat 10 files changed, 637 insertions(+), 856 deletions(-) [+]
line wrap: on
line diff
--- a/libirccd-test/CMakeLists.txt	Fri Aug 18 11:36:49 2017 +0200
+++ b/libirccd-test/CMakeLists.txt	Wed Sep 27 09:42:57 2017 +0200
@@ -29,6 +29,8 @@
         $<$<BOOL:${WITH_JS}>:${libirccd-test_SOURCE_DIR}/irccd/plugin-tester.hpp>
         $<$<BOOL:${WITH_JS}>:${libirccd-test_SOURCE_DIR}/irccd/plugin_test.cpp>
         $<$<BOOL:${WITH_JS}>:${libirccd-test_SOURCE_DIR}/irccd/plugin_test.hpp>
+        $<$<BOOL:${WITH_JS}>:${libirccd-test_SOURCE_DIR}/irccd/js_test.hpp>
+        $<$<BOOL:${WITH_JS}>:${libirccd-test_SOURCE_DIR}/irccd/plugin_test.js>
         ${libirccd-test_SOURCE_DIR}/irccd/server-tester.cpp
         ${libirccd-test_SOURCE_DIR}/irccd/server-tester.hpp
     LIBRARIES
@@ -38,4 +40,6 @@
         extern-gtest
     PUBLIC_INCLUDES
         $<BUILD_INTERFACE:${libirccd-test_SOURCE_DIR}/irccd>
+    FLAGS
+        $<BUILD_INTERFACE:IRCCD_PLUGIN_TEST="${libirccd-test_SOURCE_DIR}/irccd/plugin_test.js">
 )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-test/irccd/js_test.hpp	Wed Sep 27 09:42:57 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * js_test.hpp -- test fixture helper for Javascript modules
+ *
+ * Copyright (c) 2013-2017 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef IRCCD_JS_TEST_HPP
+#define IRCCD_JS_TEST_HPP
+
+/**
+ * \file js_test.hpp
+ * \brief Test fixture helper for Javascript modules.
+ */
+
+#include <irccd/irccd.hpp>
+#include <irccd/js_plugin.hpp>
+#include <irccd/js_irccd_module.hpp>
+
+#include "journal_server.hpp"
+
+namespace irccd {
+
+/**
+ * \brief Test fixture helper for Javascript modules.
+ */
+template <typename... Modules>
+class js_test {
+private:
+    template <typename Module>
+    inline void add()
+    {
+        Module().load(irccd_, plugin_);
+    }
+
+    template <typename M1, typename M2, typename... Tail>
+    inline void add()
+    {
+        add<M1>();
+        add<M2, Tail...>();
+    }
+
+public:
+    irccd irccd_;                               //!< Irccd instance.
+    std::shared_ptr<js_plugin> plugin_;         //!< Javascript plugin.
+    std::shared_ptr<journal_server> server_;    //!< A journal server.
+
+    /**
+     * Constructor.
+     *
+     * Create a server and a test plugin.
+     */
+    js_test(const std::string& plugin_path = IRCCD_PLUGIN_TEST)
+        : plugin_(new js_plugin("test", plugin_path))
+        , server_(new journal_server("test"))
+    {
+        // Irccd is mandatory at the moment.
+        add<js_irccd_module>();
+        add<Modules...>();
+
+        plugin_->on_load(irccd_);
+    }
+};
+
+} // !irccd
+
+#endif // !IRCCD_JS_TEST_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-test/irccd/plugin_test.js	Wed Sep 27 09:42:57 2017 +0200
@@ -0,0 +1,6 @@
+info = {
+    author: "David Demelier <markand@malikania.fr>",
+    license: "ISC",
+    summary: "Test plugin",
+    version: "1.0"
+};
--- a/tests/js-elapsedtimer/main.cpp	Fri Aug 18 11:36:49 2017 +0200
+++ b/tests/js-elapsedtimer/main.cpp	Wed Sep 27 09:42:57 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test irccd.ElapsedTimer API
+ * main.cpp -- test Irccd.ElapsedTimer API
  *
  * Copyright (c) 2013-2017 David Demelier <markand@malikania.fr>
  *
@@ -16,54 +16,36 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <gtest/gtest.h>
+#define BOOST_TEST_MODULE "ElapsedTimer Javascript API"
+#include <boost/test/unit_test.hpp>
 
 #include <thread>
 
-#include <irccd/irccd.hpp>
-#include <irccd/js_irccd_module.hpp>
 #include <irccd/js_elapsed_timer_module.hpp>
-#include <irccd/js_plugin.hpp>
-#include <irccd/service.hpp>
 
-using namespace irccd;
+#include <js_test.hpp>
+
 using namespace std::chrono_literals;
 
-class TestElapsedTimer : public testing::Test {
-protected:
-    irccd::irccd m_irccd;
-    std::shared_ptr<js_plugin> m_plugin;
+namespace irccd {
 
-    TestElapsedTimer()
-        : m_plugin(std::make_shared<js_plugin>("empty", SOURCEDIR "/empty.js"))
-    {
-        js_irccd_module().load(m_irccd, m_plugin);
-        js_elapsed_timer_module().load(m_irccd, m_plugin);
-    }
-};
+BOOST_FIXTURE_TEST_SUITE(js_elapsed_timer_suite, js_test<js_elapsed_timer_module>)
 
-TEST_F(TestElapsedTimer, standard)
+BOOST_AUTO_TEST_CASE(standard)
 {
-    try {
-        if (duk_peval_string(m_plugin->context(), "timer = new Irccd.ElapsedTimer();") != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (duk_peval_string(plugin_->context(), "timer = new Irccd.ElapsedTimer();") != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        std::this_thread::sleep_for(300ms);
+    std::this_thread::sleep_for(300ms);
 
-        if (duk_peval_string(m_plugin->context(), "result = timer.elapsed();") != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (duk_peval_string(plugin_->context(), "result = timer.elapsed();") != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_GE(duk_get_int(m_plugin->context(), -1), 250);
-        ASSERT_LE(duk_get_int(m_plugin->context(), -1), 350);
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_REQUIRE(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_REQUIRE_GE(duk_get_int(plugin_->context(), -1), 250);
+    BOOST_REQUIRE_LE(duk_get_int(plugin_->context(), -1), 350);
 }
 
-int main(int argc, char **argv)
-{
-    testing::InitGoogleTest(&argc, argv);
+} // !irccd
 
-    return RUN_ALL_TESTS();
-}
+BOOST_AUTO_TEST_SUITE_END()
--- a/tests/js-file/main.cpp	Fri Aug 18 11:36:49 2017 +0200
+++ b/tests/js-file/main.cpp	Wed Sep 27 09:42:57 2017 +0200
@@ -16,424 +16,338 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#define BOOST_TEST_MODULE "File Javascript API"
+#include <boost/test/unit_test.hpp>
+
 #include <fstream>
 
-#include <gtest/gtest.h>
+#include <irccd/js_file_module.hpp>
+
+#include <js_test.hpp>
 
-#include <irccd/irccd.hpp>
-#include <irccd/js_file_module.hpp>
-#include <irccd/js_irccd_module.hpp>
-#include <irccd/js_plugin.hpp>
-#include <irccd/service.hpp>
+namespace irccd {
 
-using namespace irccd;
-
-class TestJsFile : public testing::Test {
-protected:
-    irccd::irccd m_irccd;
-    std::shared_ptr<js_plugin> m_plugin;
+BOOST_FIXTURE_TEST_SUITE(js_file_suite, js_test<js_file_module>)
 
-    TestJsFile()
-        : m_plugin(std::make_shared<js_plugin>("empty", SOURCEDIR "/empty.js"))
-    {
-        js_irccd_module().load(m_irccd, m_plugin);
-        js_file_module().load(m_irccd, m_plugin);
-    }
-};
-
-TEST_F(TestJsFile, functionBasename)
+BOOST_AUTO_TEST_CASE(function_basename)
 {
-    try {
-        if (duk_peval_string(m_plugin->context(), "result = Irccd.File.basename('/usr/local/etc/irccd.conf');") != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (duk_peval_string(plugin_->context(), "result = Irccd.File.basename('/usr/local/etc/irccd.conf');"))
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ("irccd.conf", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST("irccd.conf" == duk_get_string(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, functionDirname)
+BOOST_AUTO_TEST_CASE(function_dirname)
 {
-    try {
-        duk_peval_string(m_plugin->context(), "result = Irccd.File.dirname('/usr/local/etc/irccd.conf');");
+    if (duk_peval_string(plugin_->context(), "result = Irccd.File.dirname('/usr/local/etc/irccd.conf');"))
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ("/usr/local/etc", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST("/usr/local/etc" == duk_get_string(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, functionExists)
+
+BOOST_AUTO_TEST_CASE(function_exists)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
-        duk_peval_string(m_plugin->context(), "result = Irccd.File.exists(directory + '/file.txt')");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    if (duk_peval_string(plugin_->context(), "result = Irccd.File.exists(directory + '/file.txt')"))
+        throw dukx_exception(plugin_->context(), -1);
+    
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, functionExists2)
+BOOST_AUTO_TEST_CASE(function_exists2)
 {
-    try {
-        duk_peval_string(m_plugin->context(), "result = Irccd.File.exists('file_which_does_not_exist.txt')");
-
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_FALSE(duk_get_boolean(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    if (duk_peval_string(plugin_->context(), "result = Irccd.File.exists('file_which_does_not_exist.txt')"))
+        throw dukx_exception(plugin_->context(), -1);
+    
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(!duk_get_boolean(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, functionRemove)
+BOOST_AUTO_TEST_CASE(function_remove)
 {
     // First create a dummy file
     std::ofstream("test-js-fs.remove");
 
-    try {
-        if (duk_peval_string(m_plugin->context(), "Irccd.File.remove('test-js-fs.remove');") != 0)
-            throw dukx_exception(m_plugin->context(), -1);
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    if (duk_peval_string(plugin_->context(), "Irccd.File.remove('test-js-fs.remove');") != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
     std::ifstream in("test-js-fs.remove");
 
-    ASSERT_FALSE(in.is_open());
+    BOOST_TEST(!in.is_open());
 }
 
-TEST_F(TestJsFile, methodBasename)
+BOOST_AUTO_TEST_CASE(method_basename)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/level-1/file-1.txt', 'r');"
-            "result = f.basename();"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/level-1/file-1.txt', 'r');"
+        "result = f.basename();"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ("file-1.txt", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST("file-1.txt" == duk_get_string(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodBasenameClosed)
+BOOST_AUTO_TEST_CASE(method_basename_closed)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/level-1/file-1.txt', 'r');"
-            "f.close();"
-            "result = f.basename();"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/level-1/file-1.txt', 'r');"
+        "f.close();"
+        "result = f.basename();"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ("file-1.txt", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST("file-1.txt" == duk_get_string(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodDirname)
+BOOST_AUTO_TEST_CASE(method_dirname)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/level-1/file-1.txt', 'r');"
-            "result = f.dirname();"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/level-1/file-1.txt', 'r');"
+        "result = f.dirname();"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ(IRCCD_TESTS_DIRECTORY "/level-1", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(IRCCD_TESTS_DIRECTORY "/level-1" == duk_get_string(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodDirnameClosed)
+BOOST_AUTO_TEST_CASE(method_dirname_closed)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/level-1/file-1.txt', 'r');"
-            "f.close();"
-            "result = f.dirname();"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/level-1/file-1.txt', 'r');"
+        "f.close();"
+        "result = f.dirname();"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ(IRCCD_TESTS_DIRECTORY "/level-1", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(IRCCD_TESTS_DIRECTORY "/level-1" == duk_get_string(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodLines)
+BOOST_AUTO_TEST_CASE(method_lines)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
-
-        auto ret = duk_peval_string(m_plugin->context(),
-            "result = new Irccd.File(directory + '/lines.txt', 'r').lines();"
-        );
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
-
-        std::vector<std::string> expected{"a", "b", "c"};
+    auto ret = duk_peval_string(plugin_->context(),
+        "result = new Irccd.File(directory + '/lines.txt', 'r').lines();"
+    );
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_EQ(expected, dukx_get_array(m_plugin->context(), -1, dukx_get_std_string));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
+
+    std::vector<std::string> expected{"a", "b", "c"};
+
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(expected == dukx_get_array(plugin_->context(), -1, dukx_get_std_string));
 }
 
-TEST_F(TestJsFile, methodSeek1)
+BOOST_AUTO_TEST_CASE(method_seek1)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/file.txt', 'r');"
-            "f.seek(Irccd.File.SeekSet, 4);"
-            "result = f.read(1);"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/file.txt', 'r');"
+        "f.seek(Irccd.File.SeekSet, 4);"
+        "result = f.read(1);"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_EQ(".", dukx_get_std_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(".", dukx_get_std_string(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodSeek1Closed)
+BOOST_AUTO_TEST_CASE(method_seek1_closed)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/file.txt', 'r');"
-            "f.close();"
-            "f.seek(Irccd.File.SeekSet, 4);"
-            "result = f.read(1);"
-            "result = typeof (result) === \"undefined\";"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/file.txt', 'r');"
+        "f.close();"
+        "f.seek(Irccd.File.SeekSet, 4);"
+        "result = f.read(1);"
+        "result = typeof (result) === \"undefined\";"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodSeek2)
+BOOST_AUTO_TEST_CASE(method_seek2)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/file.txt', 'r');"
-            "f.seek(Irccd.File.SeekSet, 2);"
-            "f.seek(Irccd.File.SeekCur, 2);"
-            "result = f.read(1);"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/file.txt', 'r');"
+        "f.seek(Irccd.File.SeekSet, 2);"
+        "f.seek(Irccd.File.SeekCur, 2);"
+        "result = f.read(1);"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_EQ(".", dukx_get_std_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST("." == dukx_get_std_string(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodSeek2Closed)
+BOOST_AUTO_TEST_CASE(method_seek2c_losed)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/file.txt', 'r');"
-            "f.close();"
-            "f.seek(Irccd.File.SeekSet, 2);"
-            "f.seek(Irccd.File.SeekCur, 2);"
-            "result = f.read(1);"
-            "result = typeof (result) === \"undefined\";"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/file.txt', 'r');"
+        "f.close();"
+        "f.seek(Irccd.File.SeekSet, 2);"
+        "f.seek(Irccd.File.SeekCur, 2);"
+        "result = f.read(1);"
+        "result = typeof (result) === \"undefined\";"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodSeek3)
+BOOST_AUTO_TEST_CASE(method_seek3)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/file.txt', 'r');"
-            "f.seek(Irccd.File.SeekEnd, -2);"
-            "result = f.read(1);"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/file.txt', 'r');"
+        "f.seek(Irccd.File.SeekEnd, -2);"
+        "result = f.read(1);"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ("x", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST("x" == duk_get_string(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodSeek3Closed)
+BOOST_AUTO_TEST_CASE(method_seek3_closed)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/file.txt', 'r');"
-            "f.close();"
-            "f.seek(Irccd.File.SeekEnd, -2);"
-            "result = f.read(1);"
-            "result = typeof (result) === \"undefined\";"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/file.txt', 'r');"
+        "f.close();"
+        "f.seek(Irccd.File.SeekEnd, -2);"
+        "result = f.read(1);"
+        "result = typeof (result) === \"undefined\";"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodRead1)
+BOOST_AUTO_TEST_CASE(method_read1)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = new Irccd.File(directory + '/file.txt', 'r');"
-            "result = f.read();"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = new Irccd.File(directory + '/file.txt', 'r');"
+        "result = f.read();"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ("file.txt", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST("file.txt" == duk_get_string(plugin_->context(), -1));
 }
 
-TEST_F(TestJsFile, methodReadline)
+BOOST_AUTO_TEST_CASE(method_readline)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "result = [];"
-            "f = new Irccd.File(directory + '/lines.txt', 'r');"
-            "for (var s; s = f.readline(); ) {"
-            "  result.push(s);"
-            "}"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "result = [];"
+        "f = new Irccd.File(directory + '/lines.txt', 'r');"
+        "for (var s; s = f.readline(); ) {"
+        "  result.push(s);"
+        "}"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
-
-        std::vector<std::string> expected{"a", "b", "c"};
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_EQ(expected, dukx_get_array(m_plugin->context(), -1, dukx_get_std_string));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    std::vector<std::string> expected{"a", "b", "c"};
+
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(expected == dukx_get_array(plugin_->context(), -1, dukx_get_std_string));
 }
 
-TEST_F(TestJsFile, methodReadlineClosed)
+BOOST_AUTO_TEST_CASE(methodReadlineClosed)
 {
-    try {
-        duk_push_string(m_plugin->context(), IRCCD_TESTS_DIRECTORY);
-        duk_put_global_string(m_plugin->context(), "directory");
+    duk_push_string(plugin_->context(), IRCCD_TESTS_DIRECTORY);
+    duk_put_global_string(plugin_->context(), "directory");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "result = [];"
-            "f = new Irccd.File(directory + '/lines.txt', 'r');"
-            "f.close();"
-            "for (var s; s = f.readline(); ) {"
-            "  result.push(s);"
-            "}"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "result = [];"
+        "f = new Irccd.File(directory + '/lines.txt', 'r');"
+        "f.close();"
+        "for (var s; s = f.readline(); ) {"
+        "  result.push(s);"
+        "}"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
-
-        std::vector<std::string> expected;
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_EQ(expected, dukx_get_array(m_plugin->context(), -1, dukx_get_std_string));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    std::vector<std::string> expected;
+
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(expected == dukx_get_array(plugin_->context(), -1, dukx_get_std_string));
 }
 
-int main(int argc, char **argv)
-{
-    testing::InitGoogleTest(&argc, argv);
+BOOST_AUTO_TEST_SUITE_END()
 
-    return RUN_ALL_TESTS();
-}
+} // !irccd
--- a/tests/js-irccd/main.cpp	Fri Aug 18 11:36:49 2017 +0200
+++ b/tests/js-irccd/main.cpp	Wed Sep 27 09:42:57 2017 +0200
@@ -16,128 +16,100 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <gtest/gtest.h>
-
-#include <irccd/irccd.hpp>
-#include <irccd/js_irccd_module.hpp>
-#include <irccd/js_plugin.hpp>
-#include <irccd/service.hpp>
-#include <irccd/sysconfig.hpp>
-
-using namespace irccd;
+#define BOOST_TEST_MODULE "Irccd Javascript API"
+#include <boost/test/unit_test.hpp>
 
-class TestJsIrccd : public testing::Test {
-protected:
-    irccd::irccd m_irccd;
-    std::shared_ptr<js_plugin> m_plugin;
+#include <js_test.hpp>
 
-    TestJsIrccd()
-        : m_plugin(std::make_shared<js_plugin>("empty", SOURCEDIR "/empty.js"))
-    {
-        js_irccd_module().load(m_irccd, m_plugin);
-    }
-};
+namespace irccd {
+
+BOOST_FIXTURE_TEST_SUITE(js_irccd_suite, js_test<js_irccd_module>)
 
-TEST_F(TestJsIrccd, version)
+BOOST_AUTO_TEST_CASE(version)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "major = Irccd.version.major;"
-            "minor = Irccd.version.minor;"
-            "patch = Irccd.version.patch;"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "major = Irccd.version.major;"
+        "minor = Irccd.version.minor;"
+        "patch = Irccd.version.patch;"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "major"));
-        ASSERT_EQ(IRCCD_VERSION_MAJOR, duk_get_int(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "minor"));
-        ASSERT_EQ(IRCCD_VERSION_MINOR, duk_get_int(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "patch"));
-        ASSERT_EQ(IRCCD_VERSION_PATCH, duk_get_int(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "major"));
+    BOOST_TEST(IRCCD_VERSION_MAJOR == duk_get_int(plugin_->context(), -1));
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "minor"));
+    BOOST_TEST(IRCCD_VERSION_MINOR == duk_get_int(plugin_->context(), -1));
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "patch"));
+    BOOST_TEST(IRCCD_VERSION_PATCH == duk_get_int(plugin_->context(), -1));
 }
 
-TEST_F(TestJsIrccd, fromJavascript)
+BOOST_AUTO_TEST_CASE(from_javascript)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "try {"
-            "  throw new Irccd.SystemError(1, 'test');"
-            "} catch (e) {"
-            "  errno = e.errno;"
-            "  name = e.name;"
-            "  message = e.message;"
-            "  v1 = (e instanceof Error);"
-            "  v2 = (e instanceof Irccd.SystemError);"
-            "}"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "try {"
+        "  throw new Irccd.SystemError(1, 'test');"
+        "} catch (e) {"
+        "  errno = e.errno;"
+        "  name = e.name;"
+        "  message = e.message;"
+        "  v1 = (e instanceof Error);"
+        "  v2 = (e instanceof Irccd.SystemError);"
+        "}"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "errno"));
-        ASSERT_EQ(1, duk_get_int(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "name"));
-        ASSERT_STREQ("SystemError", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "message"));
-        ASSERT_STREQ("test", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "v1"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "v2"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "errno"));
+    BOOST_TEST(1 == duk_get_int(plugin_->context(), -1));
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "name"));
+    BOOST_TEST("SystemError" == duk_get_string(plugin_->context(), -1));
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "message"));
+    BOOST_TEST("test" == duk_get_string(plugin_->context(), -1));
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "v1"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "v2"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
 }
 
-TEST_F(TestJsIrccd, fromNative)
+BOOST_AUTO_TEST_CASE(fromNative)
 {
-    try {
-        duk_push_c_function(m_plugin->context(), [] (duk_context *ctx) -> duk_ret_t {
-            dukx_throw(ctx, system_error(EINVAL, "hey"));
+    duk_push_c_function(plugin_->context(), [] (duk_context *ctx) -> duk_ret_t {
+        dukx_throw(ctx, system_error(EINVAL, "hey"));
 
-            return 0;
-        }, 0);
+        return 0;
+    }, 0);
 
-        duk_put_global_string(m_plugin->context(), "f");
+    duk_put_global_string(plugin_->context(), "f");
 
-        auto ret = duk_peval_string(m_plugin->context(),
-            "try {"
-            "  f();"
-            "} catch (e) {"
-            "  errno = e.errno;"
-            "  name = e.name;"
-            "  message = e.message;"
-            "  v1 = (e instanceof Error);"
-            "  v2 = (e instanceof Irccd.SystemError);"
-            "}"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "try {"
+        "  f();"
+        "} catch (e) {"
+        "  errno = e.errno;"
+        "  name = e.name;"
+        "  message = e.message;"
+        "  v1 = (e instanceof Error);"
+        "  v2 = (e instanceof Irccd.SystemError);"
+        "}"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "errno"));
-        ASSERT_EQ(EINVAL, duk_get_int(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "name"));
-        ASSERT_STREQ("SystemError", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "message"));
-        ASSERT_STREQ("hey", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "v1"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "v2"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "errno"));
+    BOOST_TEST(EINVAL == duk_get_int(plugin_->context(), -1));
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "name"));
+    BOOST_TEST("SystemError" == duk_get_string(plugin_->context(), -1));
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "message"));
+    BOOST_TEST("hey" == duk_get_string(plugin_->context(), -1));
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "v1"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "v2"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
 }
 
-int main(int argc, char **argv)
-{
-    testing::InitGoogleTest(&argc, argv);
+BOOST_AUTO_TEST_SUITE_END()
 
-    return RUN_ALL_TESTS();
-}
+} // !irccd
--- a/tests/js-system/main.cpp	Fri Aug 18 11:36:49 2017 +0200
+++ b/tests/js-system/main.cpp	Wed Sep 27 09:42:57 2017 +0200
@@ -16,70 +16,48 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <gtest/gtest.h>
+#define BOOST_TEST_MODULE "System Javascript API"
+#include <boost/test/unit_test.hpp>
 
 #include <irccd/irccd.hpp>
 #include <irccd/js_file_module.hpp>
-#include <irccd/js_irccd_module.hpp>
 #include <irccd/js_system_module.hpp>
-#include <irccd/js_plugin.hpp>
-#include <irccd/service.hpp>
-#include <irccd/sysconfig.hpp>
 #include <irccd/system.hpp>
 
-using namespace irccd;
+#include <js_test.hpp>
 
-class TestJsSystem : public testing::Test {
-protected:
-    irccd::irccd m_irccd;
-    std::shared_ptr<js_plugin> m_plugin;
+namespace irccd {
+
+using fixture = js_test<js_file_module, js_system_module>;
 
-    TestJsSystem()
-        : m_plugin(std::make_shared<js_plugin>("empty", SOURCEDIR "/empty.js"))
-    {
-        js_irccd_module().load(m_irccd, m_plugin);
-        js_file_module().load(m_irccd, m_plugin);
-        js_system_module().load(m_irccd, m_plugin);
-    }
-};
+BOOST_FIXTURE_TEST_SUITE(js_system_suite, fixture)
 
-TEST_F(TestJsSystem, home)
+BOOST_AUTO_TEST_CASE(home)
 {
-    try {
-        duk_peval_string_noresult(m_plugin->context(), "result = Irccd.System.home();");
+    duk_peval_string_noresult(plugin_->context(), "result = Irccd.System.home();");
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_EQ(sys::home(), duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(),"result"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == sys::home());
 }
 
 #if defined(HAVE_POPEN)
 
-TEST_F(TestJsSystem, popen)
+BOOST_AUTO_TEST_CASE(popen)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "f = Irccd.System.popen(\"" IRCCD_EXECUTABLE " --version\", \"r\");"
-            "r = f.readline();"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "f = Irccd.System.popen(\"" IRCCD_EXECUTABLE " --version\", \"r\");"
+        "r = f.readline();"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "r"));
-        ASSERT_STREQ(IRCCD_VERSION, duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "r"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == IRCCD_VERSION);
 }
 
 #endif
 
-int main(int argc, char **argv)
-{
-    testing::InitGoogleTest(&argc, argv);
+BOOST_AUTO_TEST_SUITE_END()
 
-    return RUN_ALL_TESTS();
-}
+} // !irccd
--- a/tests/js-timer/main.cpp	Fri Aug 18 11:36:49 2017 +0200
+++ b/tests/js-timer/main.cpp	Wed Sep 27 09:42:57 2017 +0200
@@ -16,97 +16,50 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#define BOOST_TEST_MODULE "Timer Javascript API"
+#include <boost/test/unit_test.hpp>
 #include <boost/timer/timer.hpp>
 
-#include <gtest/gtest.h>
-
-#include <irccd/irccd.hpp>
-#include <irccd/logger.hpp>
-#include <irccd/js_irccd_module.hpp>
 #include <irccd/js_plugin_module.hpp>
 #include <irccd/js_timer_module.hpp>
-#include <irccd/js_plugin.hpp>
-#include <irccd/service.hpp>
-#include <irccd/system.hpp>
 
-using namespace irccd;
-
-class TestJsTimer : public testing::Test {
-protected:
-    irccd::irccd m_irccd;
-    std::shared_ptr<js_plugin> m_plugin;
+#include <js_test.hpp>
 
-    void open(const std::string &file)
-    {
-        m_plugin = std::make_shared<js_plugin>("timer", file);
+namespace irccd {
 
-        js_irccd_module().load(m_irccd, m_plugin);
-        PluginModule().load(m_irccd, m_plugin);
-        js_timer_module().load(m_irccd, m_plugin);
-
-        m_plugin->on_load(m_irccd);
-        m_irccd.plugins().add(m_plugin);
-    }
+class fixture : public js_test<js_plugin_module, js_timer_module> {
+public:
+    using js_test::js_test;
 };
 
-TEST_F(TestJsTimer, single)
+BOOST_FIXTURE_TEST_SUITE(js_timer_suite, fixture)
+
+BOOST_AUTO_TEST_CASE(single)
 {
-    open(DIRECTORY "/timer-single.js");
+    fixture f(DIRECTORY "/timer-single.js");
 
     boost::timer::cpu_timer timer;
 
     while (timer.elapsed().wall / 1000000LL < 3000)
-        util::poller::poll(512, m_irccd);
+        util::poller::poll(512, f.irccd_);
 
-    ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "count"));
-    ASSERT_EQ(1, duk_get_int(m_plugin->context(), -1));
+    BOOST_TEST(duk_get_global_string(f.plugin_->context(), "count"));
+    BOOST_TEST(duk_get_int(f.plugin_->context(), -1) == 1);
 }
 
-TEST_F(TestJsTimer, repeat)
+BOOST_AUTO_TEST_CASE(repeat)
 {
-    open(DIRECTORY "/timer-repeat.js");
+    fixture f(DIRECTORY "/timer-repeat.js");
 
     boost::timer::cpu_timer timer;
 
     while (timer.elapsed().wall / 1000000LL < 3000)
-        util::poller::poll(512, m_irccd);
+        util::poller::poll(512, f.irccd_);
 
-    ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "count"));
-    ASSERT_GE(duk_get_int(m_plugin->context(), -1), 5);
+    BOOST_TEST(duk_get_global_string(f.plugin_->context(), "count"));
+    BOOST_TEST(duk_get_int(f.plugin_->context(), -1) >= 5);
 }
 
-#if 0
-
-/*
- * XXX: currently disabled because it will break single-shot timers.
- */
-
-TEST(Basic, pending)
-{
-    /*
-     * This test ensure that if pending actions on a stopped timer are never executed.
-     */
-    Irccd irccd;
-    boost::timer::cpu_timer timer;
-
-    auto plugin = std::make_shared<Plugin>("timer", DIRECTORY "/timer-pending.js");
+BOOST_AUTO_TEST_SUITE_END()
 
-    irccd.addPlugin(plugin);
-    irccd.poll();
-    irccd.dispatch();
-
-    ASSERT_EQ(0, plugin->context().getGlobal<int>("count"));
-}
-
-#endif
-
-int main(int argc, char **argv)
-{
-    // Needed for some components.
-    sys::set_program_name("irccd");
-    log::set_logger(std::make_unique<log::silent_logger>());
-    log::set_verbose(true);
-    testing::InitGoogleTest(&argc, argv);
-
-    return RUN_ALL_TESTS();
-}
+} // !irccd
--- a/tests/js-unicode/main.cpp	Fri Aug 18 11:36:49 2017 +0200
+++ b/tests/js-unicode/main.cpp	Wed Sep 27 09:42:57 2017 +0200
@@ -20,78 +20,50 @@
  * /!\ Be sure that this file is kept saved in UTF-8 /!\
  */
 
-#include <gtest/gtest.h>
+#define BOOST_TEST_MODULE "Unicode Javascript API"
+#include <boost/test/unit_test.hpp>
 
-#include <irccd/irccd.hpp>
-#include <irccd/js_irccd_module.hpp>
 #include <irccd/js_unicode_module.hpp>
-#include <irccd/js_plugin.hpp>
-#include <irccd/service.hpp>
-#include <irccd/system.hpp>
 
-using namespace irccd;
+#include <js_test.hpp>
 
-class TestJsUnicode : public testing::Test {
-protected:
-    irccd::irccd m_irccd;
-    std::shared_ptr<js_plugin> m_plugin;
+namespace irccd {
 
-    TestJsUnicode()
-        : m_plugin(std::make_shared<js_plugin>("empty", SOURCEDIR "/empty.js"))
-    {
-        js_irccd_module().load(m_irccd, m_plugin);
-        js_unicode_module().load(m_irccd, m_plugin);
-    }
-};
+BOOST_FIXTURE_TEST_SUITE(js_unicode_suite, js_test<js_unicode_module>)
 
-TEST_F(TestJsUnicode, isLetter)
+BOOST_AUTO_TEST_CASE(is_letter)
 {
-    try {
-        duk_peval_string_noresult(m_plugin->context(), "result = Irccd.Unicode.isLetter(String('é').charCodeAt(0));");
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
+    duk_peval_string_noresult(plugin_->context(), "result = Irccd.Unicode.isLetter(String('é').charCodeAt(0));");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
 
-        duk_peval_string_noresult(m_plugin->context(), "result = Irccd.Unicode.isLetter(String('€').charCodeAt(0));");
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_FALSE(duk_get_boolean(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    duk_peval_string_noresult(plugin_->context(), "result = Irccd.Unicode.isLetter(String('€').charCodeAt(0));");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(!duk_get_boolean(plugin_->context(), -1));
 }
 
-TEST_F(TestJsUnicode, isLower)
+BOOST_AUTO_TEST_CASE(is_lower)
 {
-    try {
-        duk_peval_string_noresult(m_plugin->context(), "result = Irccd.Unicode.isLower(String('é').charCodeAt(0));");
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
+    duk_peval_string_noresult(plugin_->context(), "result = Irccd.Unicode.isLower(String('é').charCodeAt(0));");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
 
-        duk_peval_string_noresult(m_plugin->context(), "result = Irccd.Unicode.isLower(String('É').charCodeAt(0));");
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_FALSE(duk_get_boolean(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    duk_peval_string_noresult(plugin_->context(), "result = Irccd.Unicode.isLower(String('É').charCodeAt(0));");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(!duk_get_boolean(plugin_->context(), -1));
 }
 
-TEST_F(TestJsUnicode, isUpper)
+BOOST_AUTO_TEST_CASE(is_upper)
 {
-    try {
-        duk_peval_string_noresult(m_plugin->context(), "result = Irccd.Unicode.isUpper(String('É').charCodeAt(0));");
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_TRUE(duk_get_boolean(m_plugin->context(), -1));
+    duk_peval_string_noresult(plugin_->context(), "result = Irccd.Unicode.isUpper(String('É').charCodeAt(0));");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(duk_get_boolean(plugin_->context(), -1));
 
-        duk_peval_string_noresult(m_plugin->context(), "result = Irccd.Unicode.isUpper(String('é').charCodeAt(0));");
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_FALSE(duk_get_boolean(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    duk_peval_string_noresult(plugin_->context(), "result = Irccd.Unicode.isUpper(String('é').charCodeAt(0));");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(!duk_get_boolean(plugin_->context(), -1));
 }
 
-int main(int argc, char **argv)
-{
-    testing::InitGoogleTest(&argc, argv);
+BOOST_AUTO_TEST_SUITE_END()
 
-    return RUN_ALL_TESTS();
-}
+} // !irccd
--- a/tests/js-util/main.cpp	Fri Aug 18 11:36:49 2017 +0200
+++ b/tests/js-util/main.cpp	Wed Sep 27 09:42:57 2017 +0200
@@ -16,323 +16,245 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <gtest/gtest.h>
+#define BOOST_TEST_MODULE "Unicode Javascript API"
+#include <boost/test/unit_test.hpp>
 
-#include <irccd/irccd.hpp>
-#include <irccd/js_irccd_module.hpp>
 #include <irccd/js_util_module.hpp>
-#include <irccd/js_plugin.hpp>
-#include <irccd/service.hpp>
-#include <irccd/system.hpp>
+
+#include <js_test.hpp>
 
-using namespace irccd;
+namespace irccd {
 
-class TestJsUtil : public testing::Test {
-protected:
-    irccd::irccd m_irccd;
-    std::shared_ptr<js_plugin> m_plugin;
+BOOST_FIXTURE_TEST_SUITE(js_util_suite, js_test<js_util_module>)
 
-    TestJsUtil()
-        : m_plugin(std::make_shared<js_plugin>("empty", SOURCEDIR "/empty.js"))
-    {
-        js_irccd_module().load(m_irccd, m_plugin);
-        js_util_module().load(m_irccd, m_plugin);
-    }
-};
+/*
+ * Irccd.Util misc.
+ * ------------------------------------------------------------------
+ */
 
-TEST_F(TestJsUtil, formatSimple)
+BOOST_AUTO_TEST_CASE(format_simple)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "result = Irccd.Util.format(\"#{target}\", { target: \"markand\" })"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "result = Irccd.Util.format(\"#{target}\", { target: \"markand\" })"
+    );
 
-        if (ret != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ("markand", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "markand");
 }
 
-TEST_F(TestJsUtil, splituser)
+BOOST_AUTO_TEST_CASE(splituser)
 {
-    try {
-        if (duk_peval_string(m_plugin->context(), "result = Irccd.Util.splituser(\"user!~user@hyper/super/host\");") != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (duk_peval_string(plugin_->context(), "result = Irccd.Util.splituser(\"user!~user@hyper/super/host\");") != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ("user", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "user");
 }
 
-TEST_F(TestJsUtil, splithost)
+BOOST_AUTO_TEST_CASE(splithost)
 {
-    try {
-        if (duk_peval_string(m_plugin->context(), "result = Irccd.Util.splithost(\"user!~user@hyper/super/host\");") != 0)
-            throw dukx_exception(m_plugin->context(), -1);
+    if (duk_peval_string(plugin_->context(), "result = Irccd.Util.splithost(\"user!~user@hyper/super/host\");") != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "result"));
-        ASSERT_STREQ("!~user@hyper/super/host", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "result"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "!~user@hyper/super/host");
 }
 
 /*
- * Irccd.Util.cut
+ * Irccd.Util.cut.
  * ------------------------------------------------------------------
  */
 
-TEST_F(TestJsUtil, cut_string_simple)
+BOOST_AUTO_TEST_CASE(cut_string_simple)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "lines = Irccd.Util.cut('hello world');\n"
-            "line0 = lines[0];\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "lines = Irccd.Util.cut('hello world');\n"
+        "line0 = lines[0];\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "line0"));
-        ASSERT_STREQ("hello world", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "line0"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "hello world");
 }
 
-TEST_F(TestJsUtil, cut_string_double)
+BOOST_AUTO_TEST_CASE(cut_string_double)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "lines = Irccd.Util.cut('hello world', 5);\n"
-            "line0 = lines[0];\n"
-            "line1 = lines[1];\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "lines = Irccd.Util.cut('hello world', 5);\n"
+        "line0 = lines[0];\n"
+        "line1 = lines[1];\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "line0"));
-        ASSERT_STREQ("hello", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "line1"));
-        ASSERT_STREQ("world", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "line0"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "hello");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "line1"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "world");
 }
 
-TEST_F(TestJsUtil, cut_string_dirty)
+BOOST_AUTO_TEST_CASE(cut_string_dirty)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "lines = Irccd.Util.cut('     hello    world     ', 5);\n"
-            "line0 = lines[0];\n"
-            "line1 = lines[1];\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "lines = Irccd.Util.cut('     hello    world     ', 5);\n"
+        "line0 = lines[0];\n"
+        "line1 = lines[1];\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "line0"));
-        ASSERT_STREQ("hello", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "line1"));
-        ASSERT_STREQ("world", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "line0"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "hello");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "line1"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "world");
 }
 
-TEST_F(TestJsUtil, cut_string_too_much_lines)
+BOOST_AUTO_TEST_CASE(cut_string_too_much_lines)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "lines = Irccd.Util.cut('abc def ghi jkl', 3, 3);\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "lines = Irccd.Util.cut('abc def ghi jkl', 3, 3);\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "lines"));
-        ASSERT_TRUE(duk_is_undefined(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "lines"));
+    BOOST_TEST(duk_is_undefined(plugin_->context(), -1));
 }
 
-TEST_F(TestJsUtil, cut_string_token_too_big)
+BOOST_AUTO_TEST_CASE(cut_string_token_too_big)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "try {\n"
-            "  lines = Irccd.Util.cut('hello world', 3);\n"
-            "} catch (e) {\n"
-            "  name = e.name;\n"
-            "  message = e.message;\n"
-            "}\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "try {\n"
+        "  lines = Irccd.Util.cut('hello world', 3);\n"
+        "} catch (e) {\n"
+        "  name = e.name;\n"
+        "  message = e.message;\n"
+        "}\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "name"));
-        ASSERT_STREQ("RangeError", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "message"));
-        ASSERT_STREQ("word 'hello' could not fit in maxc limit (3)", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "name"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "RangeError");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "message"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "word 'hello' could not fit in maxc limit (3)");
 }
 
-TEST_F(TestJsUtil, cut_string_negative_maxc)
+BOOST_AUTO_TEST_CASE(cut_string_negative_maxc)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "try {\n"
-            "  lines = Irccd.Util.cut('hello world', -3);\n"
-            "} catch (e) {\n"
-            "  name = e.name;\n"
-            "  message = e.message;\n"
-            "}\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "try {\n"
+        "  lines = Irccd.Util.cut('hello world', -3);\n"
+        "} catch (e) {\n"
+        "  name = e.name;\n"
+        "  message = e.message;\n"
+        "}\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "name"));
-        ASSERT_STREQ("RangeError", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "message"));
-        ASSERT_STREQ("argument 1 (maxc) must be positive", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "name"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "RangeError");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "message"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "argument 1 (maxc) must be positive");
 }
 
-TEST_F(TestJsUtil, cut_string_negative_maxl)
+BOOST_AUTO_TEST_CASE(cut_string_negative_maxl)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "try {\n"
-            "  lines = Irccd.Util.cut('hello world', undefined, -1);\n"
-            "} catch (e) {\n"
-            "  name = e.name;\n"
-            "  message = e.message;\n"
-            "}\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "try {\n"
+        "  lines = Irccd.Util.cut('hello world', undefined, -1);\n"
+        "} catch (e) {\n"
+        "  name = e.name;\n"
+        "  message = e.message;\n"
+        "}\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "name"));
-        ASSERT_STREQ("RangeError", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "message"));
-        ASSERT_STREQ("argument 2 (maxl) must be positive", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "name"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "RangeError");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "message"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "argument 2 (maxl) must be positive");
 }
 
-TEST_F(TestJsUtil, cut_array_simple)
+BOOST_AUTO_TEST_CASE(cut_array_simple)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "lines = Irccd.Util.cut([ 'hello', 'world' ]);\n"
-            "line0 = lines[0];\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "lines = Irccd.Util.cut([ 'hello', 'world' ]);\n"
+        "line0 = lines[0];\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "line0"));
-        ASSERT_STREQ("hello world", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "line0"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "hello world");
 }
 
-TEST_F(TestJsUtil, cut_array_double)
+BOOST_AUTO_TEST_CASE(cut_array_double)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "lines = Irccd.Util.cut([ 'hello', 'world' ], 5);\n"
-            "line0 = lines[0];\n"
-            "line1 = lines[1];\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "lines = Irccd.Util.cut([ 'hello', 'world' ], 5);\n"
+        "line0 = lines[0];\n"
+        "line1 = lines[1];\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "line0"));
-        ASSERT_STREQ("hello", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "line1"));
-        ASSERT_STREQ("world", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "line0"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "hello");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "line1"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "world");
 }
 
-TEST_F(TestJsUtil, cut_array_dirty)
+BOOST_AUTO_TEST_CASE(cut_array_dirty)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "lines = Irccd.Util.cut([ '   ', ' hello  ', '  world ', '    '], 5);\n"
-            "line0 = lines[0];\n"
-            "line1 = lines[1];\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "lines = Irccd.Util.cut([ '   ', ' hello  ', '  world ', '    '], 5);\n"
+        "line0 = lines[0];\n"
+        "line1 = lines[1];\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "line0"));
-        ASSERT_STREQ("hello", duk_get_string(m_plugin->context(), -1));
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "line1"));
-        ASSERT_STREQ("world", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "line0"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "hello");
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "line1"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "world");
 }
 
-TEST_F(TestJsUtil, cut_invalid_data)
+BOOST_AUTO_TEST_CASE(cut_invalid_data)
 {
-    try {
-        auto ret = duk_peval_string(m_plugin->context(),
-            "try {\n"
-            "  lines = Irccd.Util.cut(123);\n"
-            "} catch (e) {\n"
-            "  name = e.name;\n"
-            "  message = e.message;\n"
-            "}\n"
-        );
+    auto ret = duk_peval_string(plugin_->context(),
+        "try {\n"
+        "  lines = Irccd.Util.cut(123);\n"
+        "} catch (e) {\n"
+        "  name = e.name;\n"
+        "  message = e.message;\n"
+        "}\n"
+    );
 
-        if (ret != 0) {
-            throw dukx_exception(m_plugin->context(), -1);
-        }
+    if (ret != 0)
+        throw dukx_exception(plugin_->context(), -1);
 
-        ASSERT_TRUE(duk_get_global_string(m_plugin->context(), "name"));
-        ASSERT_STREQ("TypeError", duk_get_string(m_plugin->context(), -1));
-    } catch (const std::exception &ex) {
-        FAIL() << ex.what();
-    }
+    BOOST_TEST(duk_get_global_string(plugin_->context(), "name"));
+    BOOST_TEST(duk_get_string(plugin_->context(), -1) == "TypeError");
 }
 
-int main(int argc, char **argv)
-{
-    testing::InitGoogleTest(&argc, argv);
+BOOST_AUTO_TEST_SUITE_END()
 
-    return RUN_ALL_TESTS();
-}
+} // !irccd