README.md 8.13 KB
Newer Older
1
# Dynamo Testing Guidelines
Neelay Shah's avatar
Neelay Shah committed
2

3
This document provides instructions for organizing, marking, and running tests in the Dynamo project. Follow these guidelines to ensure consistency and maintainability across the test suite.
Neelay Shah's avatar
Neelay Shah committed
4

5
---
Neelay Shah's avatar
Neelay Shah committed
6

7
## Test Organization: Where to Store Tests
Neelay Shah's avatar
Neelay Shah committed
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
### Directory Structure
```
dynamo/
├── lib/
│   ├── runtime/
│   │   ├── src/
│   │   │   └── lib.rs          # Rust code + unit tests inside
│   │   └── tests/              # Rust integration tests for runtime
│   ├── llm/
│   │   └── src/
│   │       └── lib.rs          # Rust code + unit tests inside
│   │   └── tests/              # Rust integration tests for llm
│   └── ...
├── components/
│   ├── src/dynamo/
│   |   └── planner/
25
26
27
│   |   |   └── zoo.py
│   |   |   └── foo/
│   |   |   |   └── bar.py
28
│   │   │   └── tests/              # Python unit/integration tests for planner
29
30
31
│   │   │   |   └── test_zoo.py
│   │   │   |   └── foo/            # Mirror the source code file hierarchy
│   │   │   |   |   └── test_bar.py
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
│   |   └── router/
│   │   │   └── tests/
│   |   └── ...
│   ├── backend/
│   │   └── vllm
│   │   │    └── tests/             # Python unit/integration tests for backend
│   │   └── trtllm
│   │   │    └── tests/
│   │   └── trtllm
│   │   │    └── tests/
│   └── ...
├── tests/                      # End-to-end and cross-component tests
│   ├── serve/
│   ├── kvbm/
│   ├── benchmark/
│   ├── fault_tolerance/
│   └── ...
```
- Place **unit/integration tests** for a component in its `tests/` subfolder.
- Place **end-to-end (E2E) tests** and cross-component tests in `dynamo/tests/`.
- Name test files as `test_<component>_<flow>.py` for clarity.

### Test Types and Locations
| Type         | Description                              | Location              |
|--------------|------------------------------------------|-----------------------|
| Unit         | Single function/class, isolated          | `<component>/tests/`  |
| Integration  | Interactions between modules/services    | `<component>/tests/`  |
| End-to-End   | User workflows, CLI, API                 | `tests/serve/`, etc.  |
| Benchmark    | Performance/load                         | `tests/benchmark/`    |
| Stress       | Chaos, long-run, resource limits         | `tests/fault_tolerance/` |

---

## Test Marking: How to Mark Tests

Markers are required for all tests. They are used for test selection in CI and local runs.

### Marker Requirements
- Every test must have at least one **Lifecycle** marker, and **test type** and **Hardware** markers.
- **component** markers are required as applicable.

### Marker Table
| Category                | Marker(s)                | Description                        |
|-------------------------|--------------------------|------------------------------------|
| Lifecycle [required]    | pre_merge, post_merge, nightly,  weekly, release   | When the test should run           |
77
| Test Type [required]    | unit, integration, e2e, benchmark, stress, multimodal   | Nature of the test                 |
78
79
| Hardware [required]     | gpu_0, gpu_1, gpu_2,  gpu_4, gpu_8, h100      | Number/type of GPUs required       |
| Component/Framework     | vllm, trtllm, sglang, kvbm, planner, router    | Backend or component specificity   |
80
81
| Execution               | parallel                 | Test can run in parallel with pytest-xdist |
| Other                   | slow, skip, xfail, mypy, custom_build        | Special handling                   |
82
83
84
85
86
87
88
89

### Example
```python
@pytest.mark.integration
@pytest.mark.gpu_2
@pytest.mark.vllm
def test_kv_cache_multi_gpu_behavior():
    ...
Neelay Shah's avatar
Neelay Shah committed
90
91
```

92
93
### Lifecycle Marker Note
Use the marker for the earliest pipeline stage where the test must run (e.g., `@pytest.mark.pre_merge`). This ensures the test is included in that stage and all subsequent ones (e.g., nightly, release), as CI pipelines select tests marked for earlier stages.
Neelay Shah's avatar
Neelay Shah committed
94

95
96
**Example:**
If a test is marked with `@pytest.mark.pre_merge`, and the nightly pipeline runs:
Neelay Shah's avatar
Neelay Shah committed
97
```bash
98
pytest -m "e2e and (pre_merge or post_merge or nightly)"
Neelay Shah's avatar
Neelay Shah committed
99
```
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
then this test will be included in the nightly run as well.

---

## Test Execution: How to Run Tests Locally and in CI

### Environment Setup
- Use the dev container for consistency.
- Install dependencies as specified in `pyproject.toml`.
- Set the `HF_TOKEN` environment variable for HuggingFace downloads:
  ```bash
  export HF_TOKEN=your_token_here
  ```
- Model cache is located at `~/.cache/huggingface` to avoid repeated downloads.

### Running Tests
- Run all tests:
  ```bash
  pytest
  ```
- Run by marker:
  ```bash
  pytest -m "unit"
  pytest -m "integration and gpu_1"
  pytest -m "e2e and pre_merge"
  pytest -m "benchmark and vllm"
  ```
- Run by component:
  ```bash
  pytest -m planner
  pytest -m kvbm
  ```
- Show print/log output:
  ```bash
  pytest -s
  ```
- Run in container:
  ```bash
138
139
  python container/render.py --framework=${FRAMEWORK} --target=runtime --short-output
  docker build -t dynamo:${FRAMEWORK}-latest -f container/rendered.Dockerfile .
140
141
142
143
144
145
146
147
148
  ./container/run.sh --mount-workspace -it -- pytest
  ./container/run.sh --mount-workspace -it -- pytest -m [optional markers]
  ```
- CI runs use the similar instructions as running inside the container. For example, running E2E tests as part of the nightly suite inside the Dynamo-VLLM container (which requires a single GPU) can be done with:
  ```bash
  ./container/run.sh --image $VLLM_IMAGE_NAME --name $VLLM_CONTAINER_NAME -- pytest -m "e2e and gpu_1 and (pre_merge or post_merge or nightly) "
  ```

#### Running tests locally outside of a container
Neelay Shah's avatar
Neelay Shah committed
149

150
To run tests outside of the development container, ensure that you have properly setup your environment and have installed the following dependencies in your `venv`:
Neelay Shah's avatar
Neelay Shah committed
151
152

```bash
153
154
uv pip install pytest-mypy
uv pip install pytest-asyncio
Neelay Shah's avatar
Neelay Shah committed
155
```
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
---

## Rust Testing: Organization and Execution

Rust tests in Dynamo are organized as follows:
- **Unit tests** are placed within the corresponding Rust source files (e.g., `lib.rs`) using `#[cfg(test)]` modules.
- **Integration tests** are placed in the crate's `tests/` directory and must be gated behind the `integration` feature.

### Test Segmentation by Features
- Use Cargo features to enable or disable groups of tests. For example:
  ```bash
  cargo test --features planner
  ```
- Place all integration tests behind the `integration` feature gate. This ensures they are only run when explicitly enabled:
  ```bash
  cargo test --features integration
  cargo test --all-features
  ```

### Marking Slow or Special-Case Tests
- Use `#[ignore]` to mark slow or special-case tests. These tests will not run by default and must be explicitly included:
  ```bash
  cargo test -- --ignored
  ```

### Example
```rust
#[cfg(test)]
mod kv_cache_tests {
    #[test]
    fn test_kv_cache_basic() {
        // ...
    }

    #[test]
    #[ignore]
    fn test_kv_cache_long_running() {
        // ...
    }
}
Neelay Shah's avatar
Neelay Shah committed
196
197
```

198
199
200
### CI Integration
- CI runs integration tests using either `cargo test --features integration` or `cargo test --all-features`.
- Use feature gates to control which tests are included in each CI pipeline.
Neelay Shah's avatar
Neelay Shah committed
201

202
---
Neelay Shah's avatar
Neelay Shah committed
203

204
## Additional Requirements and Troubleshooting
Neelay Shah's avatar
Neelay Shah committed
205

206
207
208
209
210
211
212
213
214
215
- Tests must be deterministic; flaky tests are not permitted.
- Performance targets:
  - Unit: <15 seconds per suite
  - Integration: <5 minutes (premerge), <5 minutes (postmerge)
  - E2E: <15 minutes (premerge).
- If a test is not running, verify the filename, markers, and folder location.
- For flaky tests, remove sources of randomness or set a fixed seed. Avoid unnecessary network calls.
- For slow tests, profile and optimize, or mark as `@pytest.mark.slow`.
- If model downloads fail, ensure `HF_TOKEN` is set and network access is available.
- If coverage is insufficient, add more tests or refactor code for better testability.
Neelay Shah's avatar
Neelay Shah committed
216

217
---
Neelay Shah's avatar
Neelay Shah committed
218

219
220
## References
- [pytest documentation](https://docs.pytest.org/en/stable/)
Neelay Shah's avatar
Neelay Shah committed
221

222
For further assistance, contact the Dynamo development team.