mirror of
https://github.com/openai/codex.git
synced 2026-04-28 18:32:04 +03:00
118 lines
3.7 KiB
Markdown
118 lines
3.7 KiB
Markdown
**DOs**
|
||
- Put tests first: Keep helper fns after tests to foreground intent.
|
||
```rust
|
||
// Tests first
|
||
/// Sends a prompt and asserts the streamed message.
|
||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||
async fn full_conversation_turn_integration() { /* ... */ }
|
||
|
||
// Helpers after tests
|
||
fn write_config(codex_home: &Path, server: &MockServer) { /* ... */ }
|
||
```
|
||
- Use readable multi-line config strings: Start with a leading newline; inline variables with format!.
|
||
```rust
|
||
fs::write(
|
||
codex_home.join("config.toml"),
|
||
format!(r#"
|
||
model_provider = "mock"
|
||
model = "test-model"
|
||
|
||
[model_providers.mock]
|
||
name = "mock"
|
||
base_url = "{}/v1"
|
||
env_key = "PATH"
|
||
wire_api = "responses"
|
||
"#, server.uri()),
|
||
)?;
|
||
```
|
||
- Consider indoc for long blocks: Keep indentation tidy without left margin loss.
|
||
```rust
|
||
use indoc::formatdoc;
|
||
|
||
fs::write(
|
||
codex_home.join("config.toml"),
|
||
formatdoc!(r#"
|
||
model_provider = "mock"
|
||
model = "test-model"
|
||
|
||
[model_providers.mock]
|
||
name = "mock"
|
||
base_url = "{base}/v1"
|
||
env_key = "PATH"
|
||
wire_api = "responses"
|
||
"#, base = server.uri()),
|
||
)?;
|
||
```
|
||
- Prefer template + replace for SSE: Avoid brace-escaping hell in format! strings.
|
||
```rust
|
||
fn sse_message(text: &str) -> String {
|
||
const TEMPLATE: &str = r#"event: response.output_item.done
|
||
data: {"type":"response.output_item.done","item":{"type":"message","role":"assistant","content":[{"type":"output_text","text":"TEXT_PLACEHOLDER"}]}}
|
||
|
||
event: response.completed
|
||
data: {"type":"response.completed","response":{"id":"resp1","output":[]}}
|
||
|
||
"#;
|
||
TEMPLATE.replace("TEXT_PLACEHOLDER", text)
|
||
}
|
||
```
|
||
- Name things precisely: Use codex_home for the temp config directory.
|
||
```rust
|
||
fn write_config(codex_home: &Path, server: &MockServer) {
|
||
// ...
|
||
}
|
||
```
|
||
- Assert on the final message via file: Use --output-last-message and compare file contents.
|
||
```rust
|
||
let codex_home = TempDir::new().unwrap();
|
||
let sandbox = TempDir::new().unwrap();
|
||
write_config(codex_home.path(), &server);
|
||
|
||
let last = sandbox.path().join("last_message.txt");
|
||
|
||
let mut cmd = assert_cmd::Command::cargo_bin("codex").unwrap();
|
||
cmd.env("CODEX_HOME", codex_home.path())
|
||
.current_dir(sandbox.path())
|
||
.arg("exec")
|
||
.arg("--skip-git-repo-check")
|
||
.arg("--output-last-message")
|
||
.arg(&last)
|
||
.arg("Hello");
|
||
|
||
cmd.assert().success().stdout(predicates::str::contains("Hello, world."));
|
||
assert_eq!(fs::read_to_string(&last).unwrap().trim(), "Hello, world.");
|
||
```
|
||
- Document each test: Add a one-liner docstring explaining the behavior under test.
|
||
```rust
|
||
/// Simulates a shell tool call then verifies the assistant's follow-up.
|
||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||
async fn tool_invocation_flow() { /* ... */ }
|
||
```
|
||
|
||
**DON'Ts**
|
||
- Don’t put helpers above tests: It hides the test’s purpose and increases scrolling.
|
||
```rust
|
||
// Anti-pattern: helpers first
|
||
fn write_config(...) { /* ... */ }
|
||
#[tokio::test] async fn test_case() { /* ... */ }
|
||
```
|
||
- Don’t hand-escape JSON braces inside format!: Hard to read and easy to break.
|
||
```rust
|
||
// Anti-pattern: unreadable escaping
|
||
format!("data: {{\"text\":\"{text}\"}}");
|
||
```
|
||
- Don’t use vague names like dir or home: Be explicit about the directory’s role.
|
||
```rust
|
||
// Anti-pattern: vague
|
||
fn write_config(dir: &Path, server: &MockServer) { /* ... */ }
|
||
```
|
||
- Don’t assert only via stdout: Stream formatting can change; assert the canonical last message file.
|
||
```rust
|
||
// Anti-pattern: only stdout check
|
||
cmd.assert().stdout(predicates::str::contains("done"));
|
||
```
|
||
- Don’t omit test docstrings: Future readers shouldn’t have to infer the intent.
|
||
```rust
|
||
// Anti-pattern: no docstring
|
||
#[tokio::test] async fn full_conversation_turn_integration() { /* ... */ }
|
||
``` |