Skip to content

Commit 72c87fe

Browse files
abelsiqueiraclaude
andcommitted
Test milestone year marking behavior and improve testing docs
Add test validating attach_milestone_data\! correctly marks years with is_milestone=true for assets, flows, and both_years scenarios. Addresses the magic transformation documented in README for issue #3. Enhance testing documentation with CLI filtering, TestItem.jl patterns, and development workflow strategies to support selective test execution. Closes #3 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude Code (claude-sonnet-4-20250514) <[email protected]>
1 parent aeb6dce commit 72c87fe

File tree

2 files changed

+147
-4
lines changed

2 files changed

+147
-4
lines changed

CLAUDE.md

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,19 @@ The package uses a graph-based approach where assets (producers, consumers) are
3636

3737
### Testing
3838

39-
```bash
40-
julia --project=test -e 'using Pkg; Pkg.test()'
41-
```
39+
**Primary Testing (CLI Runner)**: `julia --project=test test/runtests.jl`
40+
**Traditional tesing**: `julia --project=test -e 'using Pkg; Pkg.test()'`
41+
**Filtered Testing**: `julia --project=test test/runtests.jl --tags fast --exclude slow`
42+
43+
The test runner supports filtering by:
44+
45+
- `--tags tag1,tag2`: Run tests with ALL specified tags
46+
- `--exclude tag1,tag2`: Skip tests with ANY specified tags
47+
- `--file filename`: Run tests from files containing substring
48+
- `--name testname`: Run tests whose name contains substring
49+
- `--pattern text`: Run tests with name/filename containing pattern
50+
- `--list-tags`: Show available tags
51+
- `--help`: Show usage help
4252

4353
### Running the main example
4454

@@ -54,7 +64,7 @@ julia --project=.
5464

5565
# Install/update dependencies
5666
julia --project=. -e 'using Pkg; Pkg.instantiate()'
57-
julia --project=. -e 'using Pkg; Pkg.resolve()'
67+
julia --project=. -e 'using Pkg; Pkg.update()'
5868
```
5969

6070
### Documentation
@@ -133,3 +143,95 @@ Key properties are schema-driven but commonly include:
133143
- `investment_cost`: Cost for commission years
134144

135145
All assets require proper milestone and commission data attachment for valid models. The exact required fields depend on the TulipaEnergyModel version being used.
146+
147+
### Testing Guidelines
148+
149+
The project uses TestItem.jl with tags for selective test execution during development.
150+
151+
#### Test Organization
152+
153+
- **File naming**: `test/test-[functionality].jl` for focused test suites
154+
- **Descriptive names**: Test names should clearly state what behavior is being verified
155+
- **Appropriate tags**: Use `:unit`, `:integration`, `:fast` for filtering during development
156+
- **Logical grouping**: Group related test scenarios within the same file
157+
158+
#### Test Dependencies
159+
160+
- **Add to test environment**: New testing dependencies go in `test/Project.toml`
161+
- **Export in common setup**: Make dependencies available via `test/common.jl`
162+
- **Follow existing patterns**: Use the established `[CommonSetup]` pattern for shared setup
163+
164+
#### Test Content Focus
165+
166+
- **Behavior verification**: Test what the code does, not how it does it
167+
- **Schema compatibility**: Tests should work across different TulipaEnergyModel versions
168+
- **Full workflow coverage**: Include integration tests that exercise `create_connection()` and complete user workflows
169+
- **Edge cases**: Test boundary conditions, error scenarios, and data combinations
170+
- **Self-contained**: Each test should be independent and not rely on execution order
171+
172+
## Testing Strategy
173+
174+
### Development Workflow
175+
176+
**During Development**: Use filtered testing to focus on relevant tests only
177+
178+
```bash
179+
# Test specific functionality during development
180+
julia --project=test test/runtests.jl --file test-year-data --tags fast
181+
julia --project=test test/runtests.jl --tags unit,fast --exclude slow
182+
```
183+
184+
**Before Commits**: Run full test suite to ensure no regressions
185+
186+
```bash
187+
julia --project=test test/runtests.jl # All tests via CLI runner
188+
julia --project=test -e 'using Pkg; Pkg.test()' # Full Pkg.test()
189+
```
190+
191+
### Testing Architecture Patterns
192+
193+
#### TestItems Organization
194+
195+
- **Strategy-per-testitem**: Create focused testitems for each major component/strategy rather than nested loops
196+
- **Shared testsnippets**: Use `@testsnippet` for per-test setup (runs each time, variables directly accessible)
197+
- **Shared testmodules**: Use `@testmodule` for one-time expensive operations like data loading/computation (runs once, accessed via module prefix)
198+
- **Combined approach**: Use both when needed - testmodules for shared expensive operations, testsnippets for per-test variables
199+
- **Comprehensive validation**: Each testitem should test multiple aspects (files, dependencies, behavior) in one place
200+
201+
#### Pattern Examples
202+
203+
**@testsnippet (per-test setup):**
204+
205+
```julia
206+
@testsnippet TestData begin
207+
tulipa = TulipaData() # Fresh instance each test
208+
add_asset!(tulipa, :test_asset, :producer)
209+
end
210+
211+
@testitem "Feature works" setup=[CommonSetup, TestData] begin
212+
@test haskey(tulipa.graph, :test_asset)
213+
end
214+
```
215+
216+
**@testmodule (one-time expensive operations):**
217+
218+
```julia
219+
@testmodule SharedAssets begin
220+
const COMPLEX_TULIPA = create_complex_test_model() # Create once
221+
const REFERENCE_CONNECTION = create_connection(COMPLEX_TULIPA) # Compute once
222+
end
223+
224+
@testitem "Validation works" setup=[CommonSetup, SharedAssets] begin
225+
@test validate_against(result, SharedAssets.REFERENCE_CONNECTION)
226+
end
227+
```
228+
229+
#### CLI Filtering for Development
230+
231+
- **Semantic tags**: Use descriptive tags like `:unit`, `:integration`, `:fast` for easy filtering
232+
- **Development workflow**: `julia --project=test test/runtests.jl --file specific_file` during development
233+
- **Add new tags to TAGS_DATA**: Update `test/runtests.jl` when introducing new tag categories
234+
235+
#### Key Development Rule
236+
237+
**When testing new tests, use the CLI approach to filter only the relevant files to test.**

test/test-year-data-determination.jl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,47 @@ end
160160
@test length(tulipa.years) == 4
161161
end
162162

163+
@testitem "Magic transformation: attach_milestone_data! marks years as is_milestone=true" tags =
164+
[:unit, :fast] setup = [CommonSetup] begin
165+
# This test explicitly verifies the README magic transformation:
166+
# "If data is attached via attach_milestone_data!, the year is further marker as is_milestone = true"
167+
# Reference: README.md "Magic transformations" section
168+
# Issue: https://github.com/TulipaEnergyModel/TulipaBuilder.jl/issues/3
169+
170+
tulipa = TulipaData()
171+
172+
# Test asset milestone data magic transformation
173+
add_asset!(tulipa, :test_producer, :producer)
174+
@test isempty(tulipa.years)
175+
176+
# Magic transformation: attach_milestone_data! → is_milestone = true
177+
attach_milestone_data!(tulipa, :test_producer, 2030, investable = true)
178+
@test haskey(tulipa.years, 2030)
179+
@test tulipa.years[2030][:is_milestone] == true
180+
181+
# Test flow milestone data magic transformation
182+
add_asset!(tulipa, :test_consumer, :consumer)
183+
add_flow!(tulipa, :test_producer, :test_consumer)
184+
185+
# Magic transformation: attach_milestone_data! on flows → is_milestone = true
186+
attach_milestone_data!(tulipa, :test_producer, :test_consumer, 2035, investable = true)
187+
@test haskey(tulipa.years, 2035)
188+
@test tulipa.years[2035][:is_milestone] == true
189+
190+
# Test both_years milestone magic transformation
191+
attach_both_years_data!(tulipa, :test_producer, 2025, 2040, initial_units = 5)
192+
@test haskey(tulipa.years, 2025) # commission year
193+
@test haskey(tulipa.years, 2040) # milestone year
194+
@test !haskey(tulipa.years[2025], :is_milestone) # commission year not milestone
195+
@test tulipa.years[2040][:is_milestone] == true # milestone year marked as milestone
196+
197+
# Verify we have 4 years total: 2025 (commission), 2030, 2035, 2040 (all milestone except 2025)
198+
@test length(tulipa.years) == 4
199+
milestone_years =
200+
[year for (year, props) in tulipa.years if get(props, :is_milestone, false)]
201+
@test Set(milestone_years) == Set([2030, 2035, 2040])
202+
end
203+
163204
@testitem "Integration test - demonstrates current system constraint with profiles" tags =
164205
[:integration, :fast] setup = [CommonSetup] begin
165206
# IMPORTANT: This test documents a current system constraint:

0 commit comments

Comments
 (0)