1pub mod test_runner;
81mod logger;
82
83extern crate core;
84
85use std::fmt::Arguments;
86use std::future::Future;
87use std::time::{Duration};
88use crate::logger::log_static_info;
89
90pub trait TestEnvironment {
91 fn start(self) -> Self;
92
93 fn before_each_test(&self) {
94 }
96
97 fn block_on<F: Future>(&self, fut: F) -> F::Output;
98
99 fn after_each_test(&self) {
100 }
102
103 fn stop(self) -> Self;
104}
105
106pub struct TestResults {
107 pub success_tests: Vec<TestResult>,
108 pub failed_tests: Vec<TestResult>,
109 pub start_up_duration: Duration,
110 pub tests_duration: Duration,
111 pub stop_duration: Duration,
112}
113
114pub struct TestResult {
115 pub name: String,
116 pub success: bool,
117 pub duration: Duration,
118}
119
120pub fn log_env_info(message: Arguments) {
121 log_static_info(message);
122}
123
124#[cfg(test)]
125mod tests {
126 use std::future::Future;
127 use std::sync::atomic::{AtomicU32, Ordering};
128 use std::thread;
129 use actix_web::{App, HttpResponse, HttpServer, Responder};
130 use actix_web::rt::SystemRunner;
131 use once_cell::sync::OnceCell;
132 use test_collector_derive::collect_test;
133 use Ordering::SeqCst;
134 use std::rc::Rc;
135 use crate::test_runner::TestRunner;
136 use crate::{log_env_info, TestEnvironment};
137
138 struct MockTestEnv {
139 system: SystemRunner,
140 before_each_call: Rc<AtomicU32>,
141 after_each_call: Rc<AtomicU32>,
142 }
143
144 impl TestEnvironment for MockTestEnv {
145 fn start(self) -> Self {
146 log_env_info(format_args!("Starting environment"));
147 log_env_info(format_args!("Setup of environment Finished"));
148 thread::spawn(move || {
149 actix_web::rt::System::new().block_on(async move {
150 HttpServer::new(move || App::new()
151 .service(hello)
152 )
153 .bind("127.0.0.1:9090")?
154 .run()
155 .await
156 })
157 });
158 return self;
159 }
160
161 fn before_each_test(&self) {
162 self.before_each_call.fetch_add(1, SeqCst);
163 }
164
165 fn block_on<F: Future>(&self, fut: F) -> F::Output {
166 self.system.block_on(fut)
167 }
168
169 fn after_each_test(&self) {
170 self.after_each_call.fetch_add(1, SeqCst);
171 }
172
173 fn stop(self) -> Self {
174 log_env_info(format_args!("Teardown started"));
175 log_env_info(format_args!("Here You can stop APP, db or any other services"));
176 log_env_info(format_args!("Teardown finished"));
177 return self;
178 }
179 }
180
181 #[actix_web::get("/")]
182 async fn hello() -> impl Responder {
183 HttpResponse::Ok().body("Hello, world!")
184 }
185
186
187 #[test]
188 #[should_panic(expected = "Some tests are Failing")]
189 fn possible_main() {
190 let system = actix_web::rt::System::new();
191 let test_runner = TestRunner::new(
192 MockTestEnv {
193 system,
194 before_each_call: Rc::new(AtomicU32::new(0)),
195 after_each_call: Rc::new(AtomicU32::new(0)),
196 }
197 );
198
199 test_runner.run();
200 }
201
202 #[test]
203 fn check_before_and_after() {
204 let system = actix_web::rt::System::new();
205 let before_each_call = Rc::new(AtomicU32::new(0));
206 let after_each_call = Rc::new(AtomicU32::new(0));
207 let test_runner = TestRunner::new(
208 MockTestEnv {
209 system,
210 before_each_call: before_each_call.clone(),
211 after_each_call: after_each_call.clone(),
212 }
213 );
214
215 test_runner.run_safe();
216 assert_eq!(before_each_call.fetch_or(0, SeqCst), 4);
217 assert_eq!(after_each_call.fetch_or(0, SeqCst), 4);
218 }
219
220 #[collect_test]
221 pub fn sync_test_failing() {
222 println!("Executed sync!");
223 assert_eq!(true, false);
224 }
225
226 #[collect_test(async)]
227 pub async fn async_test_failing() {
228 let client = reqwest::Client::builder()
229 .build()
230 .expect("error during client build");
231 let response = client.get("http://localhost:9091/").send().await;
232 assert!(response.is_ok());
233 }
234
235 #[collect_test]
236 #[test]
237 pub fn sync_test_success() {
238 println!("Executed sync!");
239 assert_eq!(true, true);
240 }
241
242 #[collect_test(async)]
243 #[actix_web::test]
244 pub async fn async_test_success() {
245 let client = reqwest::Client::builder()
246 .build()
247 .expect("error during client build");
248 let response = client.get("http://localhost:9090/").send().await;
249 assert!(response.is_ok());
250 }
251}