Part of the Syntran Labs Learning Lab catalog.
A Price Fetcher learning project built to demonstrate Spec-Driven Development with Python, executable specs, pytest, Red-Green-Refactor, dependency injection, and responsible AI-assisted engineering.
Deliberately designed, reviewed, tested, and documented as an educational engineering example — not just generated code.
A learning project demonstrating how to build professional software using Spec Driven Development (SDD) methodology. It fetches prices for Bitcoin, Gold, and currency exchange rates.
| Aspect | This Project | Real Production App |
|---|---|---|
| Purpose | Teach SDD methodology | Serve real users |
| Data | Mock data (hardcoded) | Real APIs (CoinGecko, etc.) |
| Error Handling | Basic example | Comprehensive retry/fallback logic |
| Configuration | Simple centralized | Environment-based multi-env setup |
| Focus | Red-Green-Refactor cycle | Performance, security, reliability |
Key Point: This is an educational example that uses professional architecture patterns to show students how production systems are structured — without the complexity of real APIs or deployment concerns.
# Clone and setup
git clone https://github.com/Syntran-Labs/learn-spec-driven-dev.git
cd learn-spec-driven-dev
python -m venv venv
source venv/bin/activate # or: venv\Scripts\Activate.ps1 (Windows)
# Install and run
pip install -r requirements.txt
pytest tests/ -v # Run tests (44 passing)
python -m src bitcoin # Get Bitcoin priceThis project uses professional patterns on purpose — to teach students how real systems are built. Here's why:
What It Is:
fetcher = PriceFetcher(provider=CustomProvider()) # Inject dependencyWhy It Matters for Learning:
- ✅ Testability: Students can inject mock providers (seen in
tests/) - ✅ Flexibility: Shows how to swap implementations without modifying code
- ✅ SOLID Principle: Teaches "D" in SOLID (Dependency Inversion)
- ✅ Real-world: Every production app uses this pattern
What Students Learn: "My code should depend on abstractions, not concrete implementations"
What It Is:
# src/config.py - All hardcoded test data in one place
BITCOIN_CONFIG = {...}
EXCHANGE_RATES_CONFIG = {...}
VALID_CURRENCIES = {...}Why It Matters for Learning:
- ✅ Clarity: Students instantly see where test data lives
- ✅ Maintainability: Change test data once, not scattered throughout code
- ✅ Scalability Pattern: Real apps use config files for different environments
- ✅ Separation of Concerns: Data ≠ Logic
What Students Learn: "Configuration should be separate from business logic"
What It Is:
class PriceDataProvider(Protocol):
def get_bitcoin_data(self) -> Dict[str, Any]: ...
# ... defines the contractWhy It Matters for Learning:
- ✅ Contracts: Shows how components communicate via interfaces
- ✅ Swappability: MockPriceDataProvider can become RealAPIProvider
- ✅ Testing Pattern: Easy to create test doubles
- ✅ Architecture: Demonstrates layered architecture
What Students Learn: "Define clear contracts between components"
This project demonstrates professional extensibility patterns:
from src.price_fetcher import PriceFetcher
from src.providers import MockPriceDataProvider
# Use default provider
fetcher = PriceFetcher()
# Inject a custom provider
class MyProvider(MockPriceDataProvider):
def get_bitcoin_data(self):
return {"price": 99999.0, ...}
custom_fetcher = PriceFetcher(provider=MyProvider())Just 6 focused changes following a clear pattern:
- Write
specs/ethereum.spec.yaml - Add
EthereumPricemodel insrc/models.py - Add
ETHEREUM_CONFIGtosrc/config.py - Extend
PriceDataProviderprotocol insrc/providers.py - Add
fetch_ethereum()toPriceFetcher - Add CLI command in
src/cli.py
→ Detailed guide | → Step-by-step tutorial
| Document | For | Content |
|---|---|---|
| Getting Started | New users | Installation, first commands, troubleshooting |
| Learning SDD | Students | SDD concepts, Red-Green-Refactor cycle |
| Usage Reference | Developers | CLI commands, Python API, patterns |
| Examples | Builders | Real-world use cases, integrations |
| Contributing | Contributors | How to contribute, guidelines |
| Built with AI | Everyone | How AI was used responsibly |
| Extending Architecture | Advanced learners | DI, config extraction, protocol design, extensibility |
| Tutorial: Add Ethereum | Hands-on builders | Step-by-step guide to extend with new assets |
| Acknowledgments | Everyone | Credits and thanks to projects and communities |
| Changelog | Maintainers | Version history and release notes |
| Code of Conduct | Community | Community standards and expectations |
- ✅ How to write executable specifications
- ✅ The Red-Green-Refactor cycle in practice
- ✅ Test-driven development with pytest
- ✅ Professional Python code quality
- ✅ Dependency injection patterns (Protocol-based design)
- ✅ Configuration management (separation of concerns)
- ✅ Extensible architecture (clear patterns for new features)
- ✅ Responsible AI in software development
44 tests (100%) 100% type hints Professional architecture
100% docstrings 11 documented guides Pure learning focus
DI + Config Extensible patterns Zero production cruft
Intentional Design:
- ✅ Professional patterns → Show real-world structure
- ❌ No production complexity → Keep focus on SDD methodology
- ✅ Mock data → Fast feedback loop for learning
- ❌ No deployment code → CI/CD is beyond scope
- ✅ 100% test coverage → Demonstrate test-first development
This project uses AI responsibly:
- ✅ Clear specifications first
- ✅ Every line reviewed by humans
- ✅ Comprehensive testing
- ✅ Honest transparency
- ✅ Professional quality standards
- OpenSpec — The specification framework we use
- Changelog — Version history
- Code of Conduct — Community standards
- Acknowledgments — Credits and thanks
Special thanks to:
- Fission-AI/OpenSpec — Specification framework that makes executable documentation possible
- pytest & pytest-bdd — Testing frameworks
- Python community — For amazing tools and standards
MIT License - See LICENSE file
Ready to learn SDD? Start here →