From 33c8d6b7ed9f1ab2993da405430cca2910c5c636 Mon Sep 17 00:00:00 2001 From: Théo de la Hogue Date: Wed, 16 Nov 2022 20:01:05 +0100 Subject: Testing instance representation. --- src/argaze.test/DataStructures.py | 35 +++++++- src/argaze.test/GazeFeatures.py | 165 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/argaze.test/DataStructures.py b/src/argaze.test/DataStructures.py index 5f0a4ac..c1b78d5 100644 --- a/src/argaze.test/DataStructures.py +++ b/src/argaze.test/DataStructures.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import unittest +from dataclasses import dataclass, field from argaze import DataStructures @@ -27,6 +28,12 @@ def random_data_buffer(size, data_keys): return ts_buffer +@dataclass() +class BasicDataClass(): + """Define a basic dataclass for testing purpose.""" + + value: tuple + class TestTimeStampedBufferClass(unittest.TestCase): """Test TimeStampedBuffer class.""" @@ -56,12 +63,17 @@ class TestTimeStampedBufferClass(unittest.TestCase): DataStructures.TimeStampedBuffer({"first": ""}) - def test_str(self): + def test___repr__(self): """Test TimeStampedBuffer string representation.""" - self.assertEqual(str(DataStructures.TimeStampedBuffer()), "{}") - self.assertEqual(str(DataStructures.TimeStampedBuffer({0: ""})), "{\"0\": \"\"}") - self.assertEqual(str(DataStructures.TimeStampedBuffer({0.1: ""})), "{\"0.1\": \"\"}") + self.assertEqual(repr(DataStructures.TimeStampedBuffer()), "{}") + self.assertEqual(repr(DataStructures.TimeStampedBuffer({0: ""})), "{\"0\": \"\"}") + self.assertEqual(repr(DataStructures.TimeStampedBuffer({0.1: ""})), "{\"0.1\": \"\"}") + + data = BasicDataClass((123, 456)) + ts_buffer = DataStructures.TimeStampedBuffer({0: data}) + + self.assertEqual(repr(ts_buffer), "{\"0\": {\"value\": [123, 456]}}") def test_append(self): """Test TimeStampedBuffer append method.""" @@ -170,6 +182,11 @@ class TestTimeStampedBufferClass(unittest.TestCase): self.assertEqual(ts_buffer_dataframe.columns[1], "data_B") self.assertEqual(ts_buffer_dataframe.columns[2], "data_C") + self.assertEqual(ts_buffer_dataframe.index.dtype, 'float64') + self.assertEqual(ts_buffer_dataframe["data_A"].dtype, 'object') + self.assertEqual(ts_buffer_dataframe["data_B"].dtype, 'object') + self.assertEqual(ts_buffer_dataframe["data_C"].dtype, 'object') + # Check data exclusion option ts_buffer_dataframe = ts_buffer.as_dataframe(exclude=["data_B"]) @@ -192,6 +209,16 @@ class TestTimeStampedBufferClass(unittest.TestCase): self.assertEqual(ts_buffer_dataframe.columns[2], "data_B1") self.assertEqual(ts_buffer_dataframe.columns[3], "data_C") + # Check dataframe conversion with dataclass + data = BasicDataClass((123, 456)) + ts_buffer_dataframe = DataStructures.TimeStampedBuffer({0: data}).as_dataframe() + + self.assertEqual(ts_buffer_dataframe.index.name, "timestamp") + self.assertEqual(ts_buffer_dataframe.index.size, 1) + + self.assertEqual(ts_buffer_dataframe.columns.size, 1) + self.assertEqual(ts_buffer_dataframe.columns[0], "value") + if __name__ == '__main__': unittest.main() \ No newline at end of file diff --git a/src/argaze.test/GazeFeatures.py b/src/argaze.test/GazeFeatures.py index 692b6cf..5a3c2d9 100644 --- a/src/argaze.test/GazeFeatures.py +++ b/src/argaze.test/GazeFeatures.py @@ -4,6 +4,29 @@ import unittest from argaze import GazeFeatures +import numpy + +def random_gaze_positions(size): + """ Generate random TimeStampedGazePsoitions for testing purpose. + Timestamps are current time. + GazePositions are random values. + """ + + import random + import time + + ts_gaze_positions = GazeFeatures.TimeStampedGazePositions() + + for i in range(0, size): + + # Edit gaze position + random_gaze_position = GazeFeatures.GazePosition((random.random(), random.random())) + + # Store gaze position + ts_gaze_positions[time.time()] = random_gaze_position + + return ts_gaze_positions + class TestGazePositionClass(unittest.TestCase): """Test GazePosition class.""" @@ -12,8 +35,150 @@ class TestGazePositionClass(unittest.TestCase): # Check empty GazePosition empty_gaze_position = GazeFeatures.GazePosition() + self.assertEqual(empty_gaze_position.value, (0, 0)) + self.assertEqual(empty_gaze_position[0], 0) + self.assertEqual(empty_gaze_position[1], 0) + + for v in empty_gaze_position: + self.assertEqual(v, 0) + self.assertEqual(empty_gaze_position.accuracy, 0.) + self.assertEqual(len(empty_gaze_position), 2) + self.assertEqual(empty_gaze_position.valid, True) + self.assertEqual(numpy.array(empty_gaze_position).shape, (2,)) + + # Check integer GazePosition + int_gaze_position = GazeFeatures.GazePosition((123, 456), accuracy=55) + + self.assertEqual(int_gaze_position.value, (123, 456)) + self.assertEqual(int_gaze_position[0], 123) + self.assertEqual(int_gaze_position[1], 456) + self.assertEqual(int_gaze_position.accuracy, 55) + self.assertEqual(len(int_gaze_position), 2) + self.assertEqual(int_gaze_position.valid, True) + self.assertEqual(numpy.array(empty_gaze_position).shape, (2,)) + + # Check float GazePosition + float_gaze_position = GazeFeatures.GazePosition((1.23, 4.56), accuracy=5.5) + + self.assertEqual(float_gaze_position.value, (1.23, 4.56)) + self.assertEqual(float_gaze_position[0], 1.23) + self.assertEqual(float_gaze_position[1], 4.56) + self.assertEqual(float_gaze_position.accuracy, 5.5) + self.assertEqual(len(float_gaze_position), 2) + self.assertEqual(float_gaze_position.valid, True) + self.assertEqual(numpy.array(empty_gaze_position).shape, (2,)) + + def test_properties(self): + """Test GazePosition properties cannot be modified after creation.""" + + gaze_position = GazeFeatures.GazePosition() + + # Check that gaze position value setting fails + with self.assertRaises(AttributeError): + + gaze_position.value = (123, 456) + + self.assertNotEqual(gaze_position.value, (123, 456)) + self.assertEqual(gaze_position.value, (0, 0)) + + def test___repr__(self): + """Test GazePosition string representation.""" + + # Check empty GazePosition representation + self.assertEqual(repr(GazeFeatures.GazePosition()), "{\"value\": [0, 0], \"accuracy\": 0.0}") + +class TestUnvalidGazePositionClass(unittest.TestCase): + """Test UnvalidGazePosition class.""" + + def test_new(self): + """Test UnvalidGazePosition creation.""" + + import math + + unvalid_gaze_position = GazeFeatures.UnvalidGazePosition() + + self.assertEqual(unvalid_gaze_position.value, (None, None)) + self.assertEqual(unvalid_gaze_position.accuracy, None) + self.assertEqual(unvalid_gaze_position.valid, False) + + def test___repr__(self): + """Test UnvalidGazePosition string representation.""" + + self.assertEqual(repr(GazeFeatures.UnvalidGazePosition()), "{\"value\": [null, null], \"accuracy\": null}") + +class TestTimeStampedGazePositionsClass(unittest.TestCase): + """Test TimeStampedGazePositions class.""" + + def test___setitem__(self): + """Test __setitem__ method.""" + + ts_gaze_positions = GazeFeatures.TimeStampedGazePositions() + ts_gaze_positions[0] = GazeFeatures.GazePosition() + ts_gaze_positions[1] = GazeFeatures.UnvalidGazePosition() + + # Check GazePosition is correctly stored and accessible as a GazePosition + self.assertIsInstance(ts_gaze_positions[0], GazeFeatures.GazePosition) + self.assertEqual(ts_gaze_positions[0].valid, True) + + # Check UnvalidGazePosition is correctly stored and accessible as a UnvalidGazePosition + self.assertIsInstance(ts_gaze_positions[1], GazeFeatures.UnvalidGazePosition) + self.assertEqual(ts_gaze_positions[1].valid, False) + + # Check that bad data type insertion fails + with self.assertRaises(AssertionError): + + ts_gaze_positions[2] = "This string is not a gaze position value." + + # Check final lenght + self.assertEqual(len(ts_gaze_positions), 2) + + def test___repr__(self): + """Test inherited string representation.""" + + ts_gaze_positions = GazeFeatures.TimeStampedGazePositions() + + self.assertEqual(repr(GazeFeatures.TimeStampedGazePositions()), "{}") + + ts_gaze_positions[0] = GazeFeatures.GazePosition() + + self.assertEqual(repr(ts_gaze_positions), "{\"0\": {\"value\": [0, 0], \"accuracy\": 0.0}}") + + ts_gaze_positions[0] = GazeFeatures.UnvalidGazePosition() + + self.assertEqual(repr(ts_gaze_positions), "{\"0\": {\"value\": [null, null], \"accuracy\": null}}") + + def test_as_dataframe(self): + """Test inherited as_dataframe method.""" + + ts_gaze_positions_dataframe = random_gaze_positions(10).as_dataframe() + + # Check dataframe conversion + self.assertEqual(ts_gaze_positions_dataframe.index.name, "timestamp") + self.assertEqual(ts_gaze_positions_dataframe.index.size, 10) + + self.assertEqual(ts_gaze_positions_dataframe.columns.size, 2) + self.assertEqual(ts_gaze_positions_dataframe.columns[0], "value") + self.assertEqual(ts_gaze_positions_dataframe.columns[1], "accuracy") + + self.assertEqual(ts_gaze_positions_dataframe["value"].dtype, 'object') + self.assertEqual(ts_gaze_positions_dataframe["accuracy"].dtype, 'float64') + + # Check unvalid position conversion + ts_gaze_positions = GazeFeatures.TimeStampedGazePositions() + ts_gaze_positions[0] = GazeFeatures.UnvalidGazePosition() + ts_gaze_positions_dataframe = ts_gaze_positions.as_dataframe() + + self.assertEqual(ts_gaze_positions_dataframe.index.name, "timestamp") + self.assertEqual(ts_gaze_positions_dataframe.index.size, 1) + + self.assertEqual(ts_gaze_positions_dataframe.columns.size, 2) + self.assertEqual(ts_gaze_positions_dataframe.columns[0], "value") + self.assertEqual(ts_gaze_positions_dataframe.columns[1], "accuracy") + + self.assertEqual(ts_gaze_positions_dataframe["value"].dtype, 'object') + self.assertEqual(ts_gaze_positions_dataframe["accuracy"].dtype, 'O') # Python object type if __name__ == '__main__': -- cgit v1.1