From 1998c4f631a4f5f4c315b89905d81bb6d16fd502 Mon Sep 17 00:00:00 2001 From: Martin Chang Date: Mon, 28 Jun 2021 12:49:08 +0800 Subject: [PATCH] add drogon test English doc --- ENG-18-Testing-Framework.md | 183 ++++++++++++++++++++++++++++++++++++ _Sidebar.md | 2 + 2 files changed, 185 insertions(+) create mode 100644 ENG-18-Testing-Framework.md diff --git a/ENG-18-Testing-Framework.md b/ENG-18-Testing-Framework.md new file mode 100644 index 0000000..26bc8c9 --- /dev/null +++ b/ENG-18-Testing-Framework.md @@ -0,0 +1,183 @@ +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). + +### 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. + +```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); + }); +} +``` + +Coroutines have to be wrapped inside `AsyncTask` or called through `sync_wait` due to no native support of coroutines and C++14/17 compatibility in the testing framework. + +```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()); +} +``` + +### Starting Drogon's event loop + +Some tests need Drogon's event loop running. For example, unless specsifed, HTTP clients runs on Drogon's global event loop. The following boilerplate hanles many edge cases and guarantees the event loop is running before any test starts. + +```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 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. + +```cmake +include(ParseAndAddDrogonTest) +add_executable(mytest main.cpp) +target_link_libraries(mytest PRIVATE drogon) +ParseAndAddDrogonTest(mytest) +``` + +Now the test could be ran through build system (Makefile in this case). + +```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/_Sidebar.md b/_Sidebar.md index 771347e..8bf38a3 100644 --- a/_Sidebar.md +++ b/_Sidebar.md @@ -35,6 +35,7 @@ * [Brotli info](ENG-15-Brotli) * [Coroutines](ENG-16-Coroutines) * [Redis](ENG-17-Redis) +* [Testing Frmaework](ENG-18-Testing-Framework) ## 中文文档 @@ -71,3 +72,4 @@ * [性能测试](CHN-13-性能测试) * [协程](CHN-16-协程) * [Redis](CHN-17-Redis) +* [测试框架](CHN-18-测试框架) \ No newline at end of file