Skip to content

Commit f614829

Browse files
Merge pull request #180 from Dog-Face-Development/copilot/create-test-suite-github-actions
Add comprehensive test suite with GitHub Actions CI/CD integration
2 parents 93f00f8 + 7724553 commit f614829

File tree

7 files changed

+825
-2
lines changed

7 files changed

+825
-2
lines changed

.github/workflows/tests.yml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main, develop ]
8+
9+
permissions:
10+
contents: read
11+
pull-requests: write
12+
13+
jobs:
14+
test:
15+
name: Test on Python ${{ matrix.python-version }}
16+
runs-on: ubuntu-latest
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
python-version: ["3.9", "3.10", "3.11", "3.12"]
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v5
25+
26+
- name: Set up Python ${{ matrix.python-version }}
27+
uses: actions/setup-python@v6
28+
with:
29+
python-version: ${{ matrix.python-version }}
30+
31+
- name: Install dependencies
32+
run: |
33+
python -m pip install --upgrade pip
34+
pip install -r requirements.txt
35+
36+
- name: Run tests with pytest
37+
run: |
38+
pytest tests/ -v --cov=. --cov-report=term-missing --cov-report=xml --cov-report=html
39+
40+
- name: Upload coverage reports
41+
uses: actions/upload-artifact@v4
42+
if: matrix.python-version == '3.9'
43+
with:
44+
name: coverage-reports
45+
path: |
46+
coverage.xml
47+
htmlcov/
48+
49+
- name: Display coverage summary
50+
if: matrix.python-version == '3.9'
51+
run: |
52+
echo "## Test Coverage Summary" >> $GITHUB_STEP_SUMMARY
53+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
54+
coverage report >> $GITHUB_STEP_SUMMARY
55+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
56+
57+
lint:
58+
name: Code Quality Check
59+
runs-on: ubuntu-latest
60+
61+
steps:
62+
- name: Checkout repository
63+
uses: actions/checkout@v5
64+
65+
- name: Set up Python
66+
uses: actions/setup-python@v6
67+
with:
68+
python-version: '3.9'
69+
70+
- name: Install dependencies
71+
run: |
72+
python -m pip install --upgrade pip
73+
pip install pylint
74+
75+
- name: Analyze code with pylint
76+
run: |
77+
pylint $(git ls-files '*.py') || true

requirements.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
# Project Requirements
22

3-
pytest
3+
# Testing dependencies
4+
pytest>=7.4.0
5+
pytest-cov>=4.1.0
6+
pytest-mock>=3.11.0

setup.cfg

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,22 @@ version = 1.2.0
44

55
[options.entry_points]
66
console_scripts =
7-
pyworkout = main:workout
7+
pyworkout = main:workout
8+
9+
[tool:pytest]
10+
testpaths = tests
11+
python_files = test_*.py
12+
python_classes = Test*
13+
python_functions = test_*
14+
addopts =
15+
-v
16+
--strict-markers
17+
--tb=short
18+
--cov=.
19+
--cov-report=term-missing
20+
--cov-report=html
21+
--cov-report=xml
22+
--cov-branch
23+
markers =
24+
slow: marks tests as slow (deselect with '-m "not slow"')
25+
integration: marks tests as integration tests

tests/README.md

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
# PyWorkout Test Suite
2+
3+
This directory contains the comprehensive test suite for PyWorkout. The tests are written using pytest and provide coverage for the main CLI functionality and GUI components.
4+
5+
## Test Structure
6+
7+
```
8+
tests/
9+
├── __init__.py # Package initialization
10+
├── test_main.py # Tests for main.py (CLI functionality)
11+
└── test_gui.py # Tests for gui.py (GUI components)
12+
```
13+
14+
## Test Coverage
15+
16+
The test suite includes the following test categories:
17+
18+
### Main Module Tests (`test_main.py`)
19+
20+
1. **TestWorkoutData** - Tests workout data structures
21+
- Validates workout groups are defined correctly
22+
23+
2. **TestMuscleGroupSelection** - Tests muscle group selection
24+
- Selection by number (1-7)
25+
- Selection by name (abs, quads, glutes, etc.)
26+
- Invalid selection handling
27+
- Quit during selection
28+
29+
3. **TestWorkoutCommands** - Tests CLI commands
30+
- `list` - List exercises
31+
- `start` - Start workout
32+
- `help` - Display help
33+
- `license` - Display license
34+
- `quit` - Exit program
35+
- Invalid command handling
36+
37+
4. **TestWorkoutFlow** - Tests workout flow
38+
- Start → Next → End flow
39+
- Skip functionality
40+
- Stats command
41+
42+
5. **TestVideoFunctionality** - Tests video playback
43+
- Video command on different platforms
44+
45+
6. **TestWelcomeScreen** - Tests welcome screen
46+
- Welcome message display
47+
- Day recommendation
48+
49+
7. **TestIntegration** - Integration tests
50+
- Complete workout scenarios
51+
- Multiple muscle groups
52+
53+
### GUI Module Tests (`test_gui.py`)
54+
55+
1. **TestGUIImports** - Tests GUI imports
56+
2. **TestPercentageFunction** - Tests percentage calculations
57+
3. **TestGUIComponents** - Tests GUI components
58+
59+
## Running Tests
60+
61+
### Prerequisites
62+
63+
Install test dependencies:
64+
65+
```bash
66+
pip install -r requirements.txt
67+
```
68+
69+
This installs:
70+
- pytest
71+
- pytest-cov (coverage reporting)
72+
- pytest-mock (mocking support)
73+
74+
### Running All Tests
75+
76+
Run all tests with coverage:
77+
78+
```bash
79+
pytest tests/ -v
80+
```
81+
82+
### Running Specific Test Files
83+
84+
Run main module tests:
85+
86+
```bash
87+
pytest tests/test_main.py -v
88+
```
89+
90+
Run GUI tests:
91+
92+
```bash
93+
pytest tests/test_gui.py -v
94+
```
95+
96+
### Running Specific Test Classes
97+
98+
```bash
99+
pytest tests/test_main.py::TestMuscleGroupSelection -v
100+
```
101+
102+
### Running Specific Tests
103+
104+
```bash
105+
pytest tests/test_main.py::TestMuscleGroupSelection::test_abs_selection_by_number -v
106+
```
107+
108+
## Coverage Reports
109+
110+
### Generate Coverage Report
111+
112+
```bash
113+
pytest tests/ --cov=. --cov-report=term-missing
114+
```
115+
116+
### Generate HTML Coverage Report
117+
118+
```bash
119+
pytest tests/ --cov=. --cov-report=html
120+
```
121+
122+
Then open `htmlcov/index.html` in your browser.
123+
124+
### Generate XML Coverage Report
125+
126+
```bash
127+
pytest tests/ --cov=. --cov-report=xml
128+
```
129+
130+
## Test Configuration
131+
132+
Test configuration is stored in `setup.cfg`:
133+
134+
```ini
135+
[tool:pytest]
136+
testpaths = tests
137+
python_files = test_*.py
138+
python_classes = Test*
139+
python_functions = test_*
140+
addopts =
141+
-v
142+
--strict-markers
143+
--tb=short
144+
--cov=.
145+
--cov-report=term-missing
146+
--cov-report=html
147+
--cov-report=xml
148+
--cov-branch
149+
```
150+
151+
## Continuous Integration
152+
153+
Tests are automatically run via GitHub Actions on:
154+
- Push to `main` and `develop` branches
155+
- Pull requests to `main` and `develop` branches
156+
157+
The workflow tests against multiple Python versions:
158+
- Python 3.9
159+
- Python 3.10
160+
- Python 3.11
161+
- Python 3.12
162+
163+
See `.github/workflows/tests.yml` for the full workflow configuration.
164+
165+
## Writing New Tests
166+
167+
When adding new tests, follow these guidelines:
168+
169+
1. **Naming Convention**
170+
- Test files: `test_*.py`
171+
- Test classes: `Test*`
172+
- Test functions: `test_*`
173+
174+
2. **Test Organization**
175+
- Group related tests in classes
176+
- Use descriptive test names
177+
- Add docstrings explaining what is being tested
178+
179+
3. **Mocking**
180+
- Use `@patch` for mocking input/output
181+
- Mock external dependencies (filesystem, network, etc.)
182+
183+
4. **Example Test**
184+
185+
```python
186+
@patch('builtins.print')
187+
@patch('builtins.input')
188+
def test_abs_selection(mock_input, mock_print):
189+
"""Test selecting abs muscle group."""
190+
mock_input.side_effect = ['abs', 'quit']
191+
192+
with pytest.raises(SystemExit):
193+
main.workout()
194+
195+
printed_output = [str(call) for call in mock_print.call_args_list]
196+
assert any('Ab muscle group selected' in str(call) for call in printed_output)
197+
```
198+
199+
## Troubleshooting
200+
201+
### GUI Tests Skipped
202+
203+
GUI tests may be skipped in headless environments (CI/CD). This is expected behavior as tkinter requires a display.
204+
205+
### Import Errors
206+
207+
If you encounter import errors, ensure you're running tests from the project root:
208+
209+
```bash
210+
cd /path/to/PyWorkout
211+
pytest tests/
212+
```
213+
214+
### Coverage Not Showing
215+
216+
Ensure pytest-cov is installed:
217+
218+
```bash
219+
pip install pytest-cov
220+
```
221+
222+
## Test Results
223+
224+
Current test coverage: ~54% overall
225+
- Main module: ~51% coverage
226+
- Test suite: 25 tests passing
227+
- GUI tests: 5 tests (may skip in headless environments)
228+
229+
## Contributing
230+
231+
When contributing:
232+
1. Write tests for new features
233+
2. Ensure all tests pass before submitting PR
234+
3. Aim for >80% code coverage for new code
235+
4. Follow existing test patterns and conventions

tests/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)