Skip to content

Commit

Permalink
Changed test_detumble.py to pytest framework and added a wider range …
Browse files Browse the repository at this point in the history
…of function tests
  • Loading branch information
TaylorGilg committed Dec 26, 2024
1 parent dd23bd1 commit d00832d
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 49 deletions.
1 change: 1 addition & 0 deletions .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
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@ 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:
- id: black

#- repo: local
# hooks:
# - id: run-pytest
# name: Run pytest
# entry: pytest Tests/unit_tests/test_detumble.py
# language: system
# types: [python]
153 changes: 104 additions & 49 deletions Tests/unit_tests/test_detumble.py
Original file line number Diff line number Diff line change
@@ -1,52 +1,107 @@
import unittest
# How to run:
# 1. Make sure your virtual environment is activated
# 2. pip install pytest (pytest --version to check if you already have pytest installed)
# 3. 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=/home/taylorg/spaceLab/pyProvesKit/circuitpy_flight_software

import pytest
from Batt_Board import detumble
from FC_Board 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)


class TestDetumble(unittest.TestCase):

def test_dot_product(self):
# 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)
self.assertEqual(result, 6525.0)

# testing with two different vectors
vector1 = (1, 2, 3)
vector2 = (4, 5, 6)
result = detumble.dot_product(vector1, vector2)
self.assertEqual(result, 32) # 1*4 + 2*5 + 3*6 = 32

def test_x_product(self):
mag_field_vector = (30.0, -45.0, 60.0)
ang_vel_vector = (0.0, 0.02, 0.015)
expected_result = [-1.875, 0.45, 0.6]
actual_result = detumble.x_product(
mag_field_vector, ang_vel_vector
) # cross product
self.assertAlmostEqual(actual_result[0], expected_result[0], places=5)
self.assertAlmostEqual(actual_result[1], expected_result[1], places=5)
self.assertAlmostEqual(actual_result[2], expected_result[2], places=5)
# x_product takes in tuple arguments and returns a list value

# 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 -> ex. (30.0, -45.0, 60.0)) (magnetometer reading)
# ang_vel: ang. vel. at x, y, z axis (tuple -> ex. (0.0, 0.02, 0.015)) (gyroscope reading)
def test_magnetorquer_dipole(self):
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)
# allow for small margin of error w/ floating point arithmetic
self.assertAlmostEqual(actual_result[0], expected_result[0], places=5)
self.assertAlmostEqual(actual_result[1], expected_result[1], places=5)
self.assertAlmostEqual(actual_result[2], expected_result[2], places=5)

# testing handling of division by 0
with self.assertRaises(ZeroDivisionError):
detumble.magnetorquer_dipole((0.0, 0.0, 0.0), ang_vel)


# How to run: "cd Tests" > "cd unit_tests" > "python3 test_detumble.py"
# instead of having to use unittest module "python -m unittest test_detumble.py"
if __name__ == "__main__":
unittest.main()
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]

0 comments on commit d00832d

Please sign in to comment.