sweet_cli/test_runners/
test_server.rs

1use anyhow::Result;
2use clap::Parser;
3use std::process::Child;
4use sweet::prelude::*;
5
6/// Spin up a server, run some tests, then shut it down.
7///
8#[derive(Debug, Parser)]
9pub struct TestServer {
10	/// Blocking command to build the server, ie `cargo build`
11	#[arg(long)]
12	build_server: String,
13	/// Non-blocking command to run the server, ie `cargo run --example test_server`
14	#[arg(long)]
15	run_server: String,
16	/// The test command, ie `cargo test --test integration`
17	#[arg(long)]
18	run_test: String,
19	/// How long to wait in between running the server and running the tests
20	#[arg(short, long)]
21	delay_secs: Option<f32>,
22}
23
24
25
26impl TestServer {
27	pub fn run(self) -> Result<()> {
28		self.build_server()?;
29		let mut server = self.run_server()?;
30		let result = self.run_test();
31		server.kill()?;
32		result
33	}
34	pub fn run_server(&self) -> Result<Child> {
35		let child = CommandExt::from_whitespace(&self.run_server).spawn()?;
36		Ok(child)
37	}
38
39	pub fn build_server(&self) -> Result<()> {
40		let cmd = CommandExt::from_whitespace(&self.build_server);
41		CommandExt::unwrap_status(cmd)
42	}
43
44	pub fn run_test(&self) -> Result<()> {
45		if let Some(delay) = self.delay_secs {
46			std::thread::sleep(std::time::Duration::from_secs_f32(delay));
47		}
48		let cmd = CommandExt::from_whitespace(&self.run_test);
49		CommandExt::unwrap_status(cmd)
50	}
51}
52
53
54
55
56#[cfg(test)]
57mod test {
58	use crate::prelude::*;
59	use std::time::Instant;
60	use sweet::prelude::*;
61
62	#[test]
63	fn works() {
64		let delay = 0.5;
65		let start = Instant::now();
66		TestServer {
67			build_server: "echo 'building server'".into(),
68			run_server: "echo 'running server'".into(),
69			run_test: "echo 'running tests'".into(),
70			delay_secs: Some(delay),
71		}
72		.run()
73		.unwrap();
74		expect(start.elapsed().as_secs_f32()).to_be_greater_than(delay);
75	}
76}