Skip to content

Commit 5989a6a

Browse files
committed
refactor: implement TestContext with Environment field encapsulation
- Add Environment field to TestContext with private constructor pattern - Implement explicit .init() method for TestContext initialization - Add hardcoded environment names per binary (e2e-config, e2e-provision, e2e-full) - Create environment-specific directory structure for test isolation - Fix SSH key paths to use absolute paths preventing permission errors - Update all E2E binaries to use refactored TestContext pattern This refactoring enables proper test environment isolation by ensuring each E2E test binary creates its own environment-specific directories and uses distinct environment identifiers.
1 parent 06524ee commit 5989a6a

File tree

7 files changed

+274
-226
lines changed

7 files changed

+274
-226
lines changed

docs/issues/multi-environment-support.md

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,29 +158,41 @@ Each binary now:
158158
**Example for e2e_config_tests.rs**:
159159

160160
```rust
161+
let env_name = EnvironmentName::new("e2e-config".to_string())?;
162+
let ssh_user = Username::new("torrust")?;
161163
let environment = Environment::new(
162-
EnvironmentName::new("e2e-config".to_string())?,
164+
env_name,
165+
ssh_user,
163166
ssh_private_key_path,
164167
ssh_public_key_path,
165168
);
166169

167-
let test_context = TestContext::initialized(
170+
let test_context = TestContext::from_environment(
168171
false,
169172
environment,
170-
&ssh_user,
171173
TestContextType::Container,
172-
)?;
174+
)?.init()?;
173175
```
174176

175-
### Step 5: Update TestContext
177+
### Step 5: Update TestContext ✅ COMPLETED
176178

177179
**Location**: `src/e2e/context.rs`
178180

179181
**Requirements**:
180182

181-
- Replace individual parameters with Environment entity
182-
- Maintain backward compatibility during transition
183-
- Update all dependent code
183+
- ✅ Replace individual parameters with Environment entity
184+
- ✅ Add Environment as a field in TestContext struct
185+
- ✅ Rename `initialized` to private `new` method
186+
- ✅ Make `init` method public for explicit initialization
187+
- ✅ Update all dependent code
188+
189+
**Implementation Summary**:
190+
191+
- Added `environment: Environment` field to TestContext struct
192+
- Renamed `TestContext::initialized``TestContext::new` (private)
193+
- Made `TestContext::init()` public with ownership transfer pattern
194+
- Updated all E2E binaries to use `.init()` explicitly
195+
- Updated documentation examples and comments
184196

185197
**Key Changes**:
186198

src/bin/e2e_config_tests.rs

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
//! Run with custom options:
1717
//!
1818
//! ```bash
19-
//! # Use specific environment name
20-
//! cargo run --bin e2e-config-tests -- --environment e2e-staging
21-
//!
2219
//! # Change logging format
2320
//! cargo run --bin e2e-config-tests -- --log-format json
2421
//!
@@ -67,10 +64,6 @@ use torrust_tracker_deploy::shared::Username;
6764
#[command(name = "e2e-config-tests")]
6865
#[command(about = "E2E configuration tests for Torrust Tracker Deploy using Docker containers")]
6966
struct CliArgs {
70-
/// Environment name for deployment testing (e.g., "e2e-config", "staging"). This determines the instance name and directory structure.
71-
#[arg(long, default_value = "e2e-config")]
72-
environment: String,
73-
7467
/// Logging format to use
7568
#[arg(
7669
long,
@@ -106,39 +99,32 @@ pub async fn main() -> Result<()> {
10699
info!(
107100
application = "torrust_tracker_deploy",
108101
test_suite = "e2e_config_tests",
109-
environment = %cli.environment,
110102
log_format = ?cli.log_format,
111103
"Starting E2E configuration tests with Docker containers"
112104
);
113105

114106
let test_start = Instant::now();
115107

116-
// Create Environment entity from CLI argument
117-
let env_name = EnvironmentName::new(&cli.environment)
118-
.map_err(|e| anyhow::anyhow!("Invalid environment name '{}': {}", cli.environment, e))?;
108+
// Create Environment entity with hardcoded name for this binary
109+
let env_name =
110+
EnvironmentName::new("e2e-config").expect("Hardcoded environment name should be valid");
119111

120-
let ssh_private_key_path = std::path::PathBuf::from("fixtures/testing_rsa");
121-
let ssh_public_key_path = std::path::PathBuf::from("fixtures/testing_rsa.pub");
112+
// Use absolute paths to project root for SSH keys to ensure they can be found by Ansible
113+
let project_root = std::env::current_dir().expect("Failed to get current directory");
114+
let ssh_private_key_path = project_root.join("fixtures/testing_rsa");
115+
let ssh_public_key_path = project_root.join("fixtures/testing_rsa.pub");
116+
let ssh_user = Username::new("torrust").expect("Valid hardcoded username");
122117

123118
let environment = Environment::new(
124119
env_name,
120+
ssh_user.clone(),
125121
ssh_private_key_path.clone(),
126122
ssh_public_key_path.clone(),
127123
);
128124

129-
let ssh_user = Username::new("torrust").expect("Valid hardcoded username");
130-
131-
// Extract values from Environment entity for TestContext
132-
// TODO: Update TestContext to accept Environment entity directly
133-
let test_context = TestContext::initialized(
134-
false,
135-
environment.templates_dir(),
136-
&ssh_user,
137-
environment.instance_name.clone(),
138-
ssh_private_key_path,
139-
ssh_public_key_path,
140-
TestContextType::Container,
141-
)?;
125+
// Create and initialize TestContext
126+
let test_context =
127+
TestContext::from_environment(false, environment, TestContextType::Container)?.init()?;
142128

143129
preflight_cleanup::cleanup_lingering_resources(&test_context)?;
144130

src/bin/e2e_provision_tests.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
//! Run with custom options:
1717
//!
1818
//! ```bash
19-
//! # Use specific environment name
20-
//! cargo run --bin e2e-provision-tests -- --environment e2e-staging
21-
//!
2219
//! # Keep test environment after completion (for debugging)
2320
//! cargo run --bin e2e-provision-tests -- --keep
2421
//!
@@ -66,10 +63,6 @@ struct Cli {
6663
#[arg(long)]
6764
keep: bool,
6865

69-
/// Environment name for deployment testing (e.g., "e2e-provision", "staging"). This determines the instance name and directory structure.
70-
#[arg(long, default_value = "e2e-provision")]
71-
environment: String,
72-
7366
/// Logging format to use
7467
#[arg(
7568
long,
@@ -117,27 +110,25 @@ pub async fn main() -> Result<()> {
117110
"Starting E2E provisioning tests"
118111
);
119112

120-
// Create environment entity from CLI input
121-
let environment_name = EnvironmentName::new(cli.environment)?;
122-
let ssh_private_key_path = std::path::PathBuf::from("fixtures/testing_rsa");
123-
let ssh_public_key_path = std::path::PathBuf::from("fixtures/testing_rsa.pub");
113+
// Create environment entity for e2e-provision testing
114+
let environment_name = EnvironmentName::new("e2e-provision".to_string())?;
115+
116+
// Use absolute paths to project root for SSH keys to ensure they can be found by Ansible
117+
let project_root = std::env::current_dir().expect("Failed to get current directory");
118+
let ssh_private_key_path = project_root.join("fixtures/testing_rsa");
119+
let ssh_public_key_path = project_root.join("fixtures/testing_rsa.pub");
120+
let ssh_user = Username::new("torrust").expect("Valid hardcoded username");
121+
124122
let environment = Environment::new(
125123
environment_name,
124+
ssh_user.clone(),
126125
ssh_private_key_path.clone(),
127126
ssh_public_key_path.clone(),
128127
);
129128

130-
let ssh_user = Username::new("torrust").expect("Valid hardcoded username");
131-
132-
let test_context = TestContext::initialized(
133-
cli.keep,
134-
environment.data_dir.to_string_lossy().to_string(),
135-
&ssh_user,
136-
environment.instance_name.clone(),
137-
ssh_private_key_path,
138-
ssh_public_key_path,
139-
TestContextType::VirtualMachine,
140-
)?;
129+
let test_context =
130+
TestContext::from_environment(cli.keep, environment, TestContextType::VirtualMachine)?
131+
.init()?;
141132

142133
// Perform pre-flight cleanup to remove any lingering resources from interrupted tests
143134
cleanup_lingering_resources(&test_context)?;

src/bin/e2e_tests_full.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,6 @@ struct Cli {
7373
#[arg(long)]
7474
keep: bool,
7575

76-
/// Environment name for deployment testing (e.g., "e2e-full", "staging"). This determines the instance name and directory structure.
77-
#[arg(long, default_value = "e2e-full")]
78-
environment: String,
79-
8076
/// Logging format to use
8177
#[arg(
8278
long,
@@ -119,27 +115,25 @@ pub async fn main() -> Result<()> {
119115
"Starting E2E tests"
120116
);
121117

122-
// Create environment entity from CLI input
123-
let environment_name = EnvironmentName::new(cli.environment)?;
124-
let ssh_private_key_path = std::path::PathBuf::from("fixtures/testing_rsa");
125-
let ssh_public_key_path = std::path::PathBuf::from("fixtures/testing_rsa.pub");
118+
// Create environment entity for e2e-full testing
119+
let environment_name = EnvironmentName::new("e2e-full".to_string())?;
120+
121+
// Use absolute paths to project root for SSH keys to ensure they can be found by Ansible
122+
let project_root = std::env::current_dir().expect("Failed to get current directory");
123+
let ssh_private_key_path = project_root.join("fixtures/testing_rsa");
124+
let ssh_public_key_path = project_root.join("fixtures/testing_rsa.pub");
125+
let ssh_user = Username::new("torrust").expect("Valid hardcoded username");
126+
126127
let environment = Environment::new(
127128
environment_name,
129+
ssh_user.clone(),
128130
ssh_private_key_path.clone(),
129131
ssh_public_key_path.clone(),
130132
);
131133

132-
let ssh_user = Username::new("torrust").expect("Valid hardcoded username");
133-
134-
let test_context = TestContext::initialized(
135-
cli.keep,
136-
environment.data_dir.to_string_lossy().to_string(),
137-
&ssh_user,
138-
environment.instance_name.clone(),
139-
ssh_private_key_path,
140-
ssh_public_key_path,
141-
TestContextType::VirtualMachine,
142-
)?;
134+
let test_context =
135+
TestContext::from_environment(cli.keep, environment, TestContextType::VirtualMachine)?
136+
.init()?;
143137

144138
// Perform pre-flight cleanup to remove any lingering resources from interrupted tests
145139
cleanup_lingering_resources(&test_context)?;

0 commit comments

Comments
 (0)