From 79875eb4f74c4cf8271debe4052533e52a2c8178 Mon Sep 17 00:00:00 2001 From: Martin Chang Date: Mon, 28 Jun 2021 15:05:49 +0800 Subject: [PATCH] add drogon test Chinese doc --- CHN-18-测试框架.md | 185 ++++++++++++++++++++++++++++++++++++ ENG-18-Testing-Framework.md | 6 +- 2 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 CHN-18-测试框架.md diff --git a/CHN-18-测试框架.md b/CHN-18-测试框架.md new file mode 100644 index 0000000..5c02da3 --- /dev/null +++ b/CHN-18-测试框架.md @@ -0,0 +1,185 @@ +DrogonTest 是一个内置在 Drogon 中的最小测试框架,可实现简单的异步测试和同步测试。 它用于 Drogon 自己的单元测试和集成测试。 但也可用于测试使用 Drogon 构建的应用程序。 DrogonTest 的语法受到 [GTest](https://github.com/google/googletest) 和 [Catch2](https://github.com/catchorg/Catch2) 的启发。 + +您不必为应用程序使用 DrgonTest。您可以使用喜欢的任何东西。但它是一个选择。 + +### 基本测试 + +让我们从一个简单的例子开始。您有一个函数,可以计算至某数为止之自然数之和,并想测试它的正确性。 + +```c++ +// Tell DrogonTest to generate `test::run()`. Only defined this in the main file +#define DROGON_TEST_MAIN +#include + +int sum_all(int n) +{ + int result = 1; + for(int i=2;isetPath("/"); + client->sendRequest(req, [TEST_CTX](ReqResuelt res, const HttpResponsePtr& resp) { + // There's nothing we can do if the request didn't reach the server + // or the server generated garbage. + REQUIRE(res == ReqResult::Ok); + REQUIRE(resp != nullptr); + + CHECK(resp->getStatusCode == k200Ok); + CHECK(resp->contentType() == CT_APPLICATION_JSON); + }); +} +``` + +由于测试框架支持 C++14/17 兼容性,协程必须包装在 `AsyncTask` 中或通过 `sync_wait` 调用。 + +```c++ +DROGON_TEST(RemoteAPITestCoro) +{ + auto api_test = [TEST_CTX]() { + auto client = HttpClient::newHttpClient("http://localhost:8848"); + auto req = HttpReuqest::newHttpRequest(); + req->setPath("/"); + + auto resp = co_await client->sendRequestCoro(req); + CO_REQUIRE(resp != nullptr); + CHECK(resp->getStatusCode == k200Ok); + CHECK(resp->contentType() == CT_APPLICATION_JSON); + }; + + sync_wait(api_test()); +} +``` + +### 启动 Drogon 的事件循环 + +一些测试需要 Drogon 的事件循环运行。 例如,除非特别指定,否则HTTP客户端运行在Drogon的全局事件循环上。 以下样板处理了许多边缘情况,并确保事件循环在任何测试开始之前运行: + +```c++ +int main() +{ + std::promise p1; + std::future f1 = p1.get_future(); + + // Start the main loop on another thread + std::thread thr([&]() { + // Queues the promis to be fulfilled after starting the loop + app().getLoop()->queueInLoop([]() { p1.set_value(); }); + app().run(); + }); + + // The future is only satisfied after the event loop started + f1.get(); + int status = test::run(argc, argv); + + // Ask the event loop to shutdown and wait + app().getLoop()->queueInLoop([]() { app().quit(); }); + thr.join(); + return status; +} +``` + +### CMake 集成 + +与大多数测试框架一样,DrgonTest 可以将自身集成到 CMake 中。 `ParseAndAddDrogonTest` 函数将它在源文件中看到的测试添加到 CMake 的 CTest 框架中。 + +```cmake +include(ParseAndAddDrogonTest) +add_executable(mytest main.cpp) +target_link_libraries(mytest PRIVATE drogon) +ParseAndAddDrogonTest(mytest) +``` + +现在可以通过构建系统(在本例中为 Makefile)运行测试。 + +```bash +❯ make test +Running tests... +Test project path/to/your/test/build/ + Start 1: Sum + 1/1 Test #1: Sum .................................... Passed 0.00 sec +``` \ No newline at end of file diff --git a/ENG-18-Testing-Framework.md b/ENG-18-Testing-Framework.md index 26bc8c9..a722e85 100644 --- a/ENG-18-Testing-Framework.md +++ b/ENG-18-Testing-Framework.md @@ -1,5 +1,7 @@ DrogonTest is a minimal testing framework built into drogon to enable easy asynchronous testing as well as synchronous ones. It is used for Drogon's own unittests adn integration tests. But could also be used for testing applications built with Drogon. The syntax of DrogonTest is enspired by both [GTest](https://github.com/google/googletest) and [Catch2](https://github.com/catchorg/Catch2). +You don't have to use DrogonTest for your application. Use whatever you are comfortable with. But it is an option. + ### Basic testing Let's start with a simple example. You have a synchronous function that computes the sum of natural numbers up to a given value. And you want to test it for correctness. @@ -89,7 +91,7 @@ DROGON_TEST(TestContent) } ``` -Likewise, `CO_REQUIRE` is like REQUIRE. But for coroutines. And `DEMAND` can be used when an operation failed to modify an unrecoverable global state. Which the only logical thing to do is to stop testing competely. +Likewise, `CO_REQUIRE` is like REQUIRE. But for coroutines. And `DEMAND` can be used when an operation failed and it modifies an unrecoverable global state. Which the only logical thing to do is to stop testing completely. ### Asynchronous testing @@ -163,7 +165,7 @@ int main() ### CMake integration -Like most testing frmaeworks, DrogonTest can integrate itself into CMMake. The `ParseAndAddDrogonTest` function adds tests it sees in the source file to CMake's CTest framework. +Like most testing frmaeworks, DrogonTest can integrate itself into CMake. The `ParseAndAddDrogonTest` function adds tests it sees in the source file to CMake's CTest framework. ```cmake include(ParseAndAddDrogonTest)