Skip to content

Commit 1d1324b

Browse files
authored
tests: add data and tesk unit test
1 parent 93015da commit 1d1324b

17 files changed

Lines changed: 2356 additions & 138 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,5 @@ coverage.xml
9494
*.log
9595
/weights/
9696
!/weights/.gitkeep
97+
CLAUDE.md
98+
temp/

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ If you find tfts project useful in your research, please consider cite:
280280
```
281281
@misc{tfts2020,
282282
author = {Longxing Tan},
283-
title = {Time series prediction},
283+
title = {TFTS: Time series prediction},
284284
year = {2020},
285285
publisher = {GitHub},
286286
journal = {GitHub repository},

README_CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ def build_model():
268268
```
269269
@misc{tfts2020,
270270
author = {Longxing Tan},
271-
title = {Time series prediction},
271+
title = {TFTS: Time series prediction},
272272
year = {2020},
273273
publisher = {GitHub},
274274
journal = {GitHub repository},

docs/source/index.rst

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ TFTS: TensorFlow Time Series
77

88
<a class="github-button" href="https://github.com/LongxingTan/Time-series-prediction" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star LongxingTan/Time-series-prediction on GitHub">GitHub</a>
99

10-
Welcome to TFTS (TensorFlow Time Series), a comprehensive Python library for state-of-the-art deep learning time series analysis. TFTS provides production-ready implementations of cutting-edge models for forecasting, classification, and anomaly detection tasks.
10+
Welcome to TFTS (TensorFlow Time Series), a Python library for state-of-the-art deep learning time series analysis. TFTS provides production-ready implementations of cutting-edge models for forecasting, classification, and anomaly detection tasks.
1111

1212
.. image:: https://img.shields.io/badge/License-MIT-blue.svg
1313
:target: https://opensource.org/licenses/MIT
@@ -341,11 +341,6 @@ Community and Support
341341
**Contributing**
342342
We welcome contributions! See our `Contributing Guide <https://github.com/LongxingTan/Time-series-prediction/blob/master/CONTRIBUTING.md>`_ for details.
343343

344-
**Stay Updated**
345-
- ⭐ Star the `GitHub repository <https://github.com/LongxingTan/Time-series-prediction>`_
346-
- 📰 Check the `changelog <./CHANGELOG.md>`_ for latest updates
347-
- 🐦 Follow updates on social media
348-
349344

350345
Citation
351346
--------
@@ -368,11 +363,3 @@ License
368363
-------
369364

370365
TFTS is released under the MIT License. See `LICENSE <https://github.com/LongxingTan/Time-series-prediction/blob/master/LICENSE>`_ for details.
371-
372-
373-
Indices and Tables
374-
------------------
375-
376-
* :ref:`genindex`
377-
* :ref:`modindex`
378-
* :ref:`search`

docs/source/installation.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,5 @@ Getting Help
427427

428428
If you encounter installation issues:
429429

430-
- 📖 Check the `FAQ <./faq.html>`_
431430
- 💬 Ask in `GitHub Discussions <https://github.com/LongxingTan/Time-series-prediction/discussions>`_
432431
- 🐛 Report bugs in `GitHub Issues <https://github.com/LongxingTan/Time-series-prediction/issues>`_

tests/test_data/test_get_data.py

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import unittest
2+
from unittest.mock import MagicMock, patch
23

3-
from tfts.data.get_data import get_air_passengers, get_data, get_sine
4+
import numpy as np
5+
import pandas as pd
6+
7+
from tfts.data.get_data import get_air_passengers, get_ar_data, get_data, get_sine, get_stock_data
48

59

610
class GetDataTest(unittest.TestCase):
@@ -35,3 +39,166 @@ def test_get_air_passenger_data(self):
3539
self.assertEqual(train[1].shape[1:], (predict_sequence_length, 1))
3640
self.assertEqual(valid[0].shape[1:], (train_length, 1))
3741
self.assertEqual(valid[1].shape[1:], (predict_sequence_length, 1))
42+
43+
def test_get_sine_no_test_split(self):
44+
"""Test get_sine with test_size=0 returns single tuple"""
45+
train_length = 10
46+
predict_sequence_length = 4
47+
n_examples = 50
48+
x, y = get_sine(train_length, predict_sequence_length, test_size=0, n_examples=n_examples)
49+
self.assertEqual(x.shape, (n_examples, train_length, 1))
50+
self.assertEqual(y.shape, (n_examples, predict_sequence_length, 1))
51+
self.assertIsInstance(x, np.ndarray)
52+
self.assertIsInstance(y, np.ndarray)
53+
54+
def test_get_air_passengers_no_test_split(self):
55+
"""Test get_air_passengers with test_size=0"""
56+
train_length = 10
57+
predict_sequence_length = 4
58+
x, y = get_air_passengers(train_length, predict_sequence_length, test_size=0)
59+
self.assertEqual(x.shape[1:], (train_length, 1))
60+
self.assertEqual(y.shape[1:], (predict_sequence_length, 1))
61+
62+
def test_get_data_invalid_name(self):
63+
"""Test get_data raises ValueError for unsupported dataset"""
64+
with self.assertRaises(ValueError) as context:
65+
get_data("invalid_dataset", 10, 4, 0.2)
66+
self.assertIn("unsupported data", str(context.exception))
67+
68+
def test_get_data_test_size_validation(self):
69+
"""Test get_data validates test_size parameter"""
70+
with self.assertRaises(AssertionError):
71+
get_data("sine", 10, 4, test_size=-0.1)
72+
73+
with self.assertRaises(AssertionError):
74+
get_data("sine", 10, 4, test_size=1.5)
75+
76+
def test_get_data_airpassengers(self):
77+
"""Test get_data dispatcher for airpassengers dataset"""
78+
train_length = 12
79+
predict_length = 6
80+
train, valid = get_data("airpassengers", train_length, predict_length, test_size=0.15)
81+
self.assertIsNotNone(train)
82+
self.assertIsNotNone(valid)
83+
self.assertEqual(len(train), 2)
84+
self.assertEqual(len(valid), 2)
85+
86+
def test_get_sine_data_values_in_range(self):
87+
"""Test that sine wave values are in expected range"""
88+
train_length = 20
89+
predict_length = 5
90+
x, y = get_sine(train_length, predict_length, test_size=0, n_examples=10)
91+
92+
# Sine values should be roughly in [-1, 1] range
93+
self.assertTrue(np.all(x >= -1.5))
94+
self.assertTrue(np.all(x <= 1.5))
95+
self.assertTrue(np.all(y >= -1.5))
96+
self.assertTrue(np.all(y <= 1.5))
97+
98+
def test_get_ar_data_basic(self):
99+
"""Test basic AR data generation"""
100+
df = get_ar_data(n_series=5, timesteps=100)
101+
102+
self.assertIsInstance(df, pd.DataFrame)
103+
self.assertIn("series", df.columns)
104+
self.assertIn("time_idx", df.columns)
105+
self.assertIn("value", df.columns)
106+
self.assertEqual(len(df), 5 * 100) # n_series * timesteps
107+
108+
def test_get_ar_data_with_covariates(self):
109+
"""Test AR data generation with covariates"""
110+
df = get_ar_data(n_series=3, timesteps=50, add_covariates=True)
111+
112+
self.assertIn("day_of_week", df.columns)
113+
self.assertIn("month", df.columns)
114+
self.assertIn("category", df.columns)
115+
self.assertIn("special_event", df.columns)
116+
117+
# Check value ranges
118+
self.assertTrue(df["day_of_week"].between(0, 6).all())
119+
self.assertTrue(df["month"].between(1, 13).all())
120+
self.assertTrue(df["special_event"].isin([0, 1]).all())
121+
122+
def test_get_ar_data_with_components(self):
123+
"""Test AR data generation returning components"""
124+
df, components = get_ar_data(n_series=3, timesteps=50, return_components=True)
125+
126+
self.assertIsInstance(components, dict)
127+
self.assertIn("linear_trends", components)
128+
self.assertIn("quadratic_trends", components)
129+
self.assertIn("seasonalities", components)
130+
self.assertIn("levels", components)
131+
self.assertIn("series", components)
132+
133+
def test_get_ar_data_exponential(self):
134+
"""Test AR data with exponential transformation"""
135+
df = get_ar_data(n_series=2, timesteps=50, exp=True)
136+
137+
# Exponential values should all be positive
138+
self.assertTrue((df["value"] > 0).all())
139+
140+
def test_get_ar_data_seeded_reproducibility(self):
141+
"""Test that same seed produces same data"""
142+
df1 = get_ar_data(n_series=3, timesteps=50, seed=42)
143+
df2 = get_ar_data(n_series=3, timesteps=50, seed=42)
144+
145+
pd.testing.assert_frame_equal(df1, df2)
146+
147+
def test_get_ar_data_different_seeds(self):
148+
"""Test that different seeds produce different data"""
149+
df1 = get_ar_data(n_series=3, timesteps=50, seed=42)
150+
df2 = get_ar_data(n_series=3, timesteps=50, seed=123)
151+
152+
# Values should be different
153+
self.assertFalse(df1["value"].equals(df2["value"]))
154+
155+
def test_get_ar_data_invalid_params(self):
156+
"""Test AR data validation for invalid parameters"""
157+
with self.assertRaises(ValueError):
158+
get_ar_data(n_series=0, timesteps=100)
159+
160+
with self.assertRaises(ValueError):
161+
get_ar_data(n_series=5, timesteps=-10)
162+
163+
with self.assertRaises(ValueError):
164+
get_ar_data(n_series=5, timesteps=100, noise=-0.5)
165+
166+
def test_get_ar_data_parameter_effects(self):
167+
"""Test that parameters affect data as expected"""
168+
# High noise should create more variance
169+
df_low_noise = get_ar_data(n_series=5, timesteps=100, noise=0.01, seed=42)
170+
df_high_noise = get_ar_data(n_series=5, timesteps=100, noise=1.0, seed=42)
171+
172+
# Not directly comparing variance due to random effects,
173+
# but shapes should match
174+
self.assertEqual(len(df_low_noise), len(df_high_noise))
175+
176+
def test_get_data_ar_dispatch(self):
177+
"""Test get_data dispatcher for AR data"""
178+
result = get_data("ar", train_length=10, predict_sequence_length=5, test_size=0, n_series=3, timesteps=50)
179+
180+
self.assertIsInstance(result, pd.DataFrame)
181+
self.assertEqual(len(result), 3 * 50)
182+
183+
def test_sine_data_sequence_continuity(self):
184+
"""Test that sine data maintains temporal continuity"""
185+
train_length = 10
186+
predict_length = 5
187+
x, y = get_sine(train_length, predict_length, test_size=0, n_examples=1)
188+
189+
# x and y should form a continuous sequence
190+
# This is a shape test since exact continuity depends on implementation
191+
self.assertEqual(x.shape[1], train_length)
192+
self.assertEqual(y.shape[1], predict_length)
193+
194+
def test_air_passengers_normalization(self):
195+
"""Test that air passengers data is properly normalized"""
196+
x, y = get_air_passengers(10, 4, test_size=0)
197+
198+
# Values should be normalized (roughly between -1 and 1 after normalization)
199+
self.assertTrue(np.all(x >= -1.5))
200+
self.assertTrue(np.all(x <= 1.5))
201+
202+
203+
if __name__ == "__main__":
204+
unittest.main()

0 commit comments

Comments
 (0)