Skip to content

Commit 2e2178f

Browse files
committed
refactor: Improve test isolation and dependency injection
- Replace per-request service creation with dependency injection - Add .env support for UPLOAD_DIR configuration - Implement sequential test execution to prevent race conditions - Auto-generate test problem IDs using rand
1 parent b8e27c2 commit 2e2178f

File tree

9 files changed

+496
-321
lines changed

9 files changed

+496
-321
lines changed

.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
DATABASE_URL="postgres://postgres:password@localhost:5432/coduck"
2+
UPLOAD_DIR="uploads"

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@ name = "coduck-backend"
1414
anyhow = "1.0"
1515
axum = { version = "0.8.4", features = ["json", "multipart"] }
1616
chrono = { version = "0.4.38", features = ["serde"] }
17+
dotenv = "0.15.0"
1718
git2 = "0.20.2"
1819
serde = { version = "1.0.219", features = ["derive"] }
1920
serde_json = "1.0.133"
2021
tokio = { version = "1.45.1", features = ["full"] }
2122
uuid = { version = "1.17.0", features = ["v4"] }
2223

2324
[dev-dependencies]
25+
rand = "0.9"
2426
reqwest = { version = "0.12.19", features = ["json", "rustls-tls"] }
2527
rstest = "0.25.0"
28+
serial_test = "3.2"
2629
tempfile = "3.20"

src/file_manager/git.rs

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,24 @@ use git2::{DiffOptions, IndexAddOption, Repository, StatusOptions, Time};
55
use std::path::PathBuf;
66
use tokio::fs;
77

8-
const UPLOAD_DIR: &str = "uploads";
98
const DEFAULT_DIRECTORIES: [&str; 3] = ["solutions", "tests", "statements"];
109

1110
#[derive(Debug)]
1211
struct GitManager {
1312
problem_id: u32,
14-
base_path: Option<PathBuf>,
13+
base_path: PathBuf,
1514
}
1615

1716
impl GitManager {
18-
fn new(problem_id: u32) -> Self {
17+
fn new(problem_id: u32, base_path: PathBuf) -> Self {
1918
Self {
2019
problem_id,
21-
base_path: None,
22-
}
23-
}
24-
25-
fn new_with_path(problem_id: u32, base_path: PathBuf) -> Self {
26-
Self {
27-
problem_id,
28-
base_path: Some(base_path),
20+
base_path,
2921
}
3022
}
3123

3224
fn get_upload_path(&self) -> PathBuf {
33-
if let Some(ref base_path) = self.base_path {
34-
base_path.join(self.problem_id.to_string())
35-
} else {
36-
PathBuf::from(UPLOAD_DIR).join(self.problem_id.to_string())
37-
}
25+
self.base_path.join(self.problem_id.to_string())
3826
}
3927

4028
fn git_init(&self) -> Result<()> {
@@ -211,6 +199,7 @@ struct FileInfo {
211199
#[cfg(test)]
212200
mod tests {
213201
use super::*;
202+
use rand::Rng;
214203
use rstest::rstest;
215204
use std::path::Path;
216205
use tempfile::TempDir;
@@ -244,8 +233,8 @@ mod tests {
244233
#[tokio::test]
245234
async fn can_init_git_repository() -> Result<(), std::io::Error> {
246235
let temp_dir = TempDir::new()?;
247-
let problem_id = 10;
248-
let git_manager = GitManager::new_with_path(problem_id, temp_dir.path().to_path_buf());
236+
let problem_id = rand::rng().random_range(0..=u32::MAX);
237+
let git_manager = GitManager::new(problem_id, temp_dir.path().to_path_buf());
249238
assert!(git_manager.git_init().is_ok());
250239
assert!(Path::new(git_manager.get_upload_path().to_str().unwrap()).exists());
251240
assert!(Path::new(
@@ -259,8 +248,8 @@ mod tests {
259248
#[tokio::test]
260249
async fn can_set_config() -> Result<(), std::io::Error> {
261250
let temp_dir = TempDir::new()?;
262-
let problem_id = 11;
263-
let git_manager = GitManager::new_with_path(problem_id, temp_dir.path().to_path_buf());
251+
let problem_id = rand::rng().random_range(0..=u32::MAX);
252+
let git_manager = GitManager::new(problem_id, temp_dir.path().to_path_buf());
264253
assert!(git_manager.git_init().is_ok());
265254
let repo = git_manager.get_repository().unwrap();
266255
let config = repo.config().unwrap();
@@ -276,8 +265,8 @@ mod tests {
276265
#[tokio::test]
277266
async fn can_create_default_file() -> Result<(), std::io::Error> {
278267
let temp_dir = TempDir::new()?;
279-
let problem_id = 12;
280-
let git_manager = GitManager::new_with_path(problem_id, temp_dir.path().to_path_buf());
268+
let problem_id = rand::rng().random_range(0..=u32::MAX);
269+
let git_manager = GitManager::new(problem_id, temp_dir.path().to_path_buf());
281270
assert!(git_manager.create_default_directories().await.is_ok());
282271
assert!(Path::new(
283272
format!(
@@ -306,8 +295,8 @@ mod tests {
306295
#[tokio::test]
307296
async fn can_create_problem() -> Result<(), std::io::Error> {
308297
let temp_dir = TempDir::new()?;
309-
let problem_id = 13;
310-
let git_manager = GitManager::new_with_path(problem_id, temp_dir.path().to_path_buf());
298+
let problem_id = rand::rng().random_range(0..=u32::MAX);
299+
let git_manager = GitManager::new(problem_id, temp_dir.path().to_path_buf());
311300
assert!(git_manager.create_problem().await.is_ok());
312301
assert!(Path::new(git_manager.get_upload_path().to_str().unwrap()).exists());
313302
assert!(Path::new(
@@ -341,8 +330,8 @@ mod tests {
341330
#[tokio::test]
342331
async fn can_get_git_status() -> Result<(), tokio::io::Error> {
343332
let temp_dir = TempDir::new()?;
344-
let problem_id = 14;
345-
let git_manager = GitManager::new_with_path(problem_id, temp_dir.path().to_path_buf());
333+
let problem_id = rand::rng().random_range(0..=u32::MAX);
334+
let git_manager = GitManager::new(problem_id, temp_dir.path().to_path_buf());
346335

347336
git_manager.git_init().unwrap();
348337

@@ -387,8 +376,8 @@ mod tests {
387376
#[tokio::test]
388377
async fn can_git_add() -> Result<(), tokio::io::Error> {
389378
let temp_dir = TempDir::new()?;
390-
let problem_id = 15;
391-
let git_manager = GitManager::new_with_path(problem_id, temp_dir.path().to_path_buf());
379+
let problem_id = rand::rng().random_range(0..=u32::MAX);
380+
let git_manager = GitManager::new(problem_id, temp_dir.path().to_path_buf());
392381

393382
git_manager.git_init().unwrap();
394383

@@ -433,8 +422,8 @@ mod tests {
433422
#[tokio::test]
434423
async fn can_commit() -> Result<(), tokio::io::Error> {
435424
let temp_dir = TempDir::new()?;
436-
let problem_id = 16;
437-
let git_manager = GitManager::new_with_path(problem_id, temp_dir.path().to_path_buf());
425+
let problem_id = rand::rng().random_range(0..=u32::MAX);
426+
let git_manager = GitManager::new(problem_id, temp_dir.path().to_path_buf());
438427
git_manager.git_init().unwrap();
439428

440429
fs::create_dir_all(format!(
@@ -475,8 +464,8 @@ mod tests {
475464
#[tokio::test]
476465
async fn can_get_log() -> Result<(), tokio::io::Error> {
477466
let temp_dir = TempDir::new()?;
478-
let problem_id = 17;
479-
let git_manager = GitManager::new_with_path(problem_id, temp_dir.path().to_path_buf());
467+
let problem_id = rand::rng().random_range(0..=u32::MAX);
468+
let git_manager = GitManager::new(problem_id, temp_dir.path().to_path_buf());
480469
git_manager.git_init().unwrap();
481470
git_manager.create_default_directories().await.unwrap();
482471

0 commit comments

Comments
 (0)