Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created unit tests for detumble.py #57

Merged
merged 8 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,31 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: psf/black@stable
- name: Set up Python
uses: actions/setup-python@v5
with:
options: "--check --verbose"
src: "./"
version: ~= 24.4
python-version: '3.x'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Test with pytest
run: |
make fmt
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Test with pytest
run: |
make test
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

__pycache__/
.pytest_cache
.DS_Store
CircuitPy/.DS_Store
CircuitPy/FC_Board/.DS_Store
Expand Down
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ repos:
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files

- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
Expand Down
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"python.testing.pytestArgs": [
"CircuitPy"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
2 changes: 1 addition & 1 deletion FC_Board/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

"""
Built for the PySquared FC Board
Version: 2.0.0
Version: 2.0.0
Published: Nov 19, 2024
"""

Expand Down
Empty file added FC_Board/tests/__init__.py
Empty file.
106 changes: 106 additions & 0 deletions FC_Board/tests/test_detumble.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# After following the necessary steps in README.md, you can use "make test" to run all tests in the unit_tests folder
# To run this file specifically: cd Tests > cd unit_tests > pytest test_detumble.py
# pytest test_detumble.py -v displays which tests ran and their respective results (fail or pass)
# Note: If you encounter a ModuleNotFoundError, try: export PYTHONPATH=<path to this repo>

import pytest

# from Batt_Board import detumble
import detumble


def test_dot_product():
# dot_product is only ever called to give the square of mag_field
mag_field_vector = (30.0, 45.0, 60.0)
result = detumble.dot_product(mag_field_vector, mag_field_vector)
assert result == 6525.0 # 30.0*30.0 + 45.0*45.0 + 60.0*60.0 = 6525.0


def test_dot_product_negatives():
# testing with negative vectors
vector1 = (-1, -2, -3)
vector2 = (-4, -5, -6)
result = detumble.dot_product(vector1, vector2)
assert result == 32 # -1*-4 + -2*-5 + -3*-6


def test_dot_product_large_val():
# testing with large value vectors
vector1 = (1e6, 1e6, 1e6)
vector2 = (1e6, 1e6, 1e6)
result = detumble.dot_product(vector1, vector2)
assert result == 3e12 # 1e6*1e6 + 1e6*1e6 + 1e6*1e6 = 3e12


def test_dot_product_zero():
# testing with zero values
vector = (0.0, 0.0, 0.0)
result = detumble.dot_product(vector, vector)
assert result == 0.0


def test_x_product():
mag_field_vector = (30.0, 45.0, 60.0)
ang_vel_vector = (0.0, 0.02, 0.015)
expected_result = [-0.525, 0.45, 0.6]
# x_product takes in tuple arguments and returns a list value
actual_result = detumble.x_product(
mag_field_vector, ang_vel_vector
) # cross product
assert pytest.approx(actual_result[0], 0.001) == expected_result[0]
assert pytest.approx(actual_result[1], 0.001) == expected_result[1]
assert pytest.approx(actual_result[2], 0.001) == expected_result[2]
# due to floating point arithmetic, accept answer within 5 places


def test_x_product_negatives():
mag_field_vector = (-30.0, -45.0, -60.0)
ang_vel_vector = (-0.02, -0.02, -0.015)
expected_result = [-0.525, -0.75, -0.3]
actual_result = detumble.x_product(mag_field_vector, ang_vel_vector)
assert pytest.approx(actual_result[0], 0.001) == expected_result[0]
assert pytest.approx(actual_result[1], 0.001) == expected_result[1]
assert pytest.approx(actual_result[2], 0.001) == expected_result[2]


def test_x_product_large_val():
mag_field_vector = (1e6, 1e6, 1e6)
ang_vel_vector = (1e6, 1e6, 1e6) # cross product of parallel vector equals 0
result = detumble.x_product(mag_field_vector, ang_vel_vector)
assert result == [0.0, 0.0, 0.0]


def test_x_product_zero():
mag_field_vector = (0.0, 0.0, 0.0)
ang_vel_vector = (0.0, 0.02, 0.015)
result = detumble.x_product(mag_field_vector, ang_vel_vector)
assert result == [0.0, 0.0, 0.0]


# Bigger context: magnetorquer_dipole() is called by do_detumble() in (FC board) functions.py & (Batt Board) battery_functions.py
# mag_field: mag. field strength at x, y, & z axis (tuple) (magnetometer reading)
# ang_vel: ang. vel. at x, y, z axis (tuple) (gyroscope reading)
def test_magnetorquer_dipole():
mag_field = (30.0, -45.0, 60.0)
ang_vel = (0.0, 0.02, 0.015)
expected_result = [0.023211, -0.00557, -0.007426]
actual_result = detumble.magnetorquer_dipole(mag_field, ang_vel)
assert pytest.approx(actual_result[0], 0.001) == expected_result[0]
assert pytest.approx(actual_result[1], 0.001) == expected_result[1]
assert pytest.approx(actual_result[2], 0.001) == expected_result[2]


def test_magnetorquer_dipole_zero_mag_field():
# testing throwing of exception when mag_field = 0 (division by 0)
mag_field = (0.0, 0.0, 0.0)
ang_vel = (0.0, 0.02, 0.015)
with pytest.raises(ZeroDivisionError):
detumble.magnetorquer_dipole(mag_field, ang_vel)


def test_magnetorquer_dipole_zero_ang_vel():
# testing ang_vel with zero value
mag_field = (30.0, -45.0, 60.0)
ang_vel = (0.0, 0.0, 0.0)
result = detumble.magnetorquer_dipole(mag_field, ang_vel)
assert result == [0.0, 0.0, 0.0]
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.PHONY: fmt
fmt:
pre-commit run --all-files

.PHONY: test
test:
pytest FC_Board/tests
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ For CircuitPython load new software by doing the following:
import storage
storage.erase_filesystem()
```
4. The target board will now disappear and remount. Once remounted, copy and paste the contents of the flight software folder for the target board from your GitHub repo.
4. The target board will now disappear and remount. Once remounted copy and paste the contents of the flight software folder for the target board from your GitHub repo.
5. When the new files are onboard you can verify that all the hardware on the board is working properly by opening a serial connection and typing one of the two following commands:

__For Flight Controller Board__
Expand All @@ -43,10 +43,12 @@ We have a few python tools to make development safer, easier, and more consisten
Everytime you make a change in git, it's called a commit. We have a tool called a precommit hook that will run before you make each commit to ensure your code is safe and formatted correctly.

To install the precommit hook:

1. Install the precommit hook with `pre-commit install`

To run the precommit hook:
1. Run the precomit hook against all files with `pre-commit run --all-files`

1. Run the precommit hook against all files with `make fmt`

## General Structure:
- **boot.py** This is the code that runs on boot and initializes the stack limit
Expand Down Expand Up @@ -79,3 +81,8 @@ This software contains all of the libraries required to operate the sensors, pys
- **pysquared_rfm9x.py** This is a library that implements all the radio hardware. This code is a modified version of the pycubed_rfm9x which is a modified version of the adafruit_rfm9x file.
## tests
This software is used for performing tests on the satellite

## Testing setup

1. Follow the steps to set up your venv and install packages in the linting setup
2. Run tests with `make test`
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ click==8.1.7
distlib==0.3.8
filelock==3.15.4
identify==2.6.0
exceptiongroup==1.2.2
iniconfig==2.0.0
mypy-extensions==1.0.0
nodeenv==1.9.1
packaging==24.1
pathspec==0.12.1
platformdirs==4.2.2
pre-commit==3.8.0
PyYAML==6.0.1
pluggy==1.5.0
pytest==8.3.2
tomli==2.0.1
typing_extensions==4.12.2
virtualenv==20.26.3
Loading