Skip to content
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
669ccc4
scripts to extract to tests
deven367 Jul 1, 2025
7b08d20
extracted tests for the `common` module
deven367 Jul 1, 2025
99f12e2
tests for `losses`
deven367 Jul 1, 2025
b156d41
tests for first six models
deven367 Jul 1, 2025
83a429d
tests for vanilla transformer
deven367 Jul 1, 2025
36e793d
tests for remaining models
deven367 Jul 1, 2025
a81a27d
test for `utils`
deven367 Jul 1, 2025
11c844b
extracted tests for `core`
deven367 Jul 1, 2025
1508631
tests converted to pytest format
deven367 Jul 2, 2025
62e0123
global fixtures for models
deven367 Jul 2, 2025
82c917a
refactor and add `AutoRNN` test
deven367 Jul 2, 2025
96025a4
helper function of checking `model_args`
deven367 Jul 2, 2025
27860da
refactor and add `AutoLSTM` test
deven367 Jul 2, 2025
2e5c957
refactored tests for models and their respective AutoModels
deven367 Jul 2, 2025
7a017f2
working tests for `tsdataset`
deven367 Jul 3, 2025
b6e2b70
fix imports
deven367 Jul 3, 2025
755ae76
pytest workflow
deven367 Jul 3, 2025
31bed02
Merge branch 'main' into rm-nbdev
deven367 Jul 10, 2025
0e0d725
Merge branch 'main' into rm-nbdev
deven367 Jul 11, 2025
e7cd47f
Merge branch 'main' into rm-nbdev
deven367 Jul 18, 2025
66ae2c0
convert to pytest
deven367 Jul 21, 2025
38a09ee
remove plotting logic from tests
deven367 Jul 21, 2025
020579d
test with `assert` instead of `fastcore`
deven367 Jul 21, 2025
5736ce6
fix test errors in `core`
deven367 Jul 23, 2025
f7bcef3
MPS FALLBACK for macos runner
deven367 Jul 23, 2025
82de993
Merge branch 'main' into rm-nbdev
deven367 Jul 23, 2025
41cf5ab
init py
deven367 Jul 24, 2025
137d7db
fix conditional logic
deven367 Jul 24, 2025
fd8d842
relative import
deven367 Jul 24, 2025
bc1da8e
fix issue for np scalar
deven367 Jul 25, 2025
09fff7e
parameterize step_size, test_size
deven367 Jul 25, 2025
2fd856a
parameterize scalar_type
deven367 Jul 25, 2025
b532cc7
use model imports from `MODEL_FILENAME_DICT`
deven367 Jul 25, 2025
a0b43ca
rm unused imports
deven367 Jul 25, 2025
c0800df
replace fastcore based tests
deven367 Jul 25, 2025
0058ee0
lint
deven367 Jul 29, 2025
33da8ab
minor fixes
deven367 Jul 29, 2025
0f02004
skip installing `ray` on py3.13 on windows
deven367 Jul 29, 2025
dcbd610
set env variable through the fixture
deven367 Jul 29, 2025
96eb2be
drop support for py3.13
deven367 Jul 29, 2025
d142f41
Revert "skip installing `ray` on py3.13 on windows"
deven367 Jul 29, 2025
36591b5
additional logic to disable mps on macos runners in CI
deven367 Jul 30, 2025
3db1169
change macos runner to `macos-15-xlarge`
deven367 Jul 31, 2025
a96afcd
try `macos-14-xlarge`
deven367 Jul 31, 2025
3410ce8
Merge branch 'main' into rm-nbdev
deven367 Aug 14, 2025
3a99afd
fix asserts and parameterize tests
deven367 Aug 14, 2025
96a52b9
parameterize tests
deven367 Aug 14, 2025
d5bc0ba
parameterize tests and clean up
deven367 Aug 14, 2025
6247887
test on windows and linux to test everything works
deven367 Aug 14, 2025
252d890
mention reason for no test for timellm
deven367 Aug 14, 2025
c7188da
clean up and fixtures
deven367 Aug 14, 2025
4bd773a
reduce size of generate_series for tests
deven367 Aug 14, 2025
ab65349
cleanup
deven367 Aug 14, 2025
0b82c45
set env before imports
deven367 Aug 14, 2025
8fb3da8
Revert "test on windows and linux to test everything works"
deven367 Aug 14, 2025
a31a53b
explicitly set env and try again
deven367 Aug 14, 2025
c605a2a
override dep for `macos`
deven367 Aug 15, 2025
841002d
test on other os as well
deven367 Aug 15, 2025
53bc0b8
ignore model tests on macos
deven367 Aug 15, 2025
5e2d82e
remove NHITS test from scalars
deven367 Aug 15, 2025
4ae42ba
parameterize more tests
deven367 Aug 15, 2025
60af4c3
ignore more model tests for macos
deven367 Aug 15, 2025
863b0ef
fix __name__ bug
deven367 Aug 15, 2025
2191e09
add revin tests
deven367 Aug 15, 2025
6be87da
rename test
deven367 Aug 15, 2025
1cb4a3c
fix tolerance issue
deven367 Aug 15, 2025
d71bee2
fix syntax in numpy losses
deven367 Aug 15, 2025
21acb02
refactor fixture
deven367 Aug 15, 2025
c539875
remove extra models from tests as they have the same BaseModel
deven367 Aug 15, 2025
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
34 changes: 34 additions & 0 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: pytest

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
all-tests:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-14-xlarge, windows-latest]
python-version: ['3.9', '3.10', '3.11', '3.12']
steps:
- name: Clone repo
uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: pip install uv pytest && uv pip install --system ".[dev]" fugue[dask,spark]>=0.8.1 "dask<=2024.12.1"

- name: Run pytest
run: pytest tests
2 changes: 1 addition & 1 deletion nbs/losses.numpy.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@
" smape = _divide_no_nan(delta_y, scale)\n",
" smape = 2 * np.average(smape, weights=weights, axis=axis)\n",
" \n",
" if isinstance(smape, float):\n",
" if np.isscalar(smape):\n",
" assert smape <= 2, 'SMAPE should be lower than 200'\n",
" else:\n",
" assert all(smape <= 2), 'SMAPE should be lower than 200'\n",
Expand Down
2 changes: 1 addition & 1 deletion neuralforecast/losses/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def smape(
smape = _divide_no_nan(delta_y, scale)
smape = 2 * np.average(smape, weights=weights, axis=axis)

if isinstance(smape, float):
if np.isscalar(smape):
assert smape <= 2, "SMAPE should be lower than 200"
else:
assert all(smape <= 2), "SMAPE should be lower than 200"
Expand Down
1,740 changes: 1,740 additions & 0 deletions scripts/cli.ipynb

Large diffs are not rendered by default.

110 changes: 110 additions & 0 deletions scripts/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# AUTOGENERATED! DO NOT EDIT! File to edit: cli.ipynb.

# %% auto 0
__all__ = ['tst_flags', 'to_skip', 'mapper', 'print_execs', 'print_hide', 'other_tests', 'get_markdown', 'get_code',
'extract_dir', 'no_dir_and_dir', 'get_all_tests2', 'get_all_tests', 'print_dir_in_nb']

# %% cli.ipynb 1
from functools import partial

from execnb.nbio import read_nb
from fastcore.script import call_parse
from fastcore.xtras import Path, globtastic
from nbdev import nbdev_export
from nbdev.export import ExportModuleProc, nb_export
from nbdev.maker import ModuleMaker
from nbdev.processors import NBProcessor


# %% cli.ipynb 4
tst_flags = 'datasets distributed matplotlib polars pyarrow scipy'.split()
to_skip = [
'showdoc',
'load_ext',
'from nbdev'
]


def print_execs(cell):
if 'exec' in cell.source: print(cell.source)

def print_hide(cell):
if 'hide' in cell.directives_: print(cell.source)

def other_tests(cell):
if len(cell.directives_) == 0:
print(cell.source)

def get_markdown(cell):
if cell.cell_type == "markdown":
print(cell.source)

def get_code(cell):
if cell.cell_type == "code":
print(cell.source)

def extract_dir(cell, dirs):
for directive in dirs.split(','):
if directive in cell.directives_:
print(cell.source)

def no_dir_and_dir(cell, dir):
if len(cell.directives_) == 0:
print(cell.source)

if dir in cell.directives_:
print(cell.source)

def get_all_tests2(cell):
if cell.cell_type == "code":

if len(cell.directives_) == 0:
print(cell.source)


elif any(x in tst_flags + ['hide'] for x in cell.directives_):
# if not (x in cell.source for x in to_skip):
print(cell.source)

def get_all_tests(cell):
if len(cell.directives_) == 0:
print(cell.source)

if any(x in tst_flags + ["hide"] for x in cell.directives_):
print(cell.source)



# %% cli.ipynb 8
mapper = {
'print_execs': print_execs,
'print_hide': print_hide,
'other_tests': other_tests,
'get_markdown': get_markdown,
'extract_dir': extract_dir,
'no_dir_and_dir': no_dir_and_dir,
'get_all_tests':get_all_tests,
'get_all_tests2':get_all_tests2
}

# %% cli.ipynb 9
@call_parse
def print_dir_in_nb(nb_path:str,
dir:str=None,
dir_name:str=None,
):
if dir_name not in mapper.keys():
raise ValueError(f'Choose processor from the the following: {mapper.keys()}')

if dir_name == 'extract_dir':
processor = NBProcessor(nb_path, partial(extract_dir, dir=dir))
processor.process()
return
elif dir_name == 'no_dir_and_dir':
processor = NBProcessor(nb_path, partial(no_dir_and_dir, dir=dir))
processor.process()
return

processor = NBProcessor(nb_path, mapper[dir_name])
processor.process()

2 changes: 2 additions & 0 deletions scripts/cvt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from nbdev.export import nb_export
nb_export('cli.ipynb', lib_path='.', name='cli')
40 changes: 40 additions & 0 deletions scripts/extract_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash

echo Python: $(which python)
source /Users/deven367/miniforge3/bin/activate
conda activate nixtla

echo Activated env: $(which python)


mkdir -p ../tests

tst_flags='datasets distributed matplotlib polars pyarrow scipy'

nbs=$(ls ../nbs/*.ipynb)
# echo "Available notebooks: $nbs"


# this approach3 that was discussed on Slack
# mkdir -p ../tests3
# for flag in $tst_flags; do
# # echo "Extracting $flag"

# for nb in $nbs; do
# # get name of notebook without extension
# nb_name=$(basename "$nb" .ipynb)

# # echo "Processing notebook: $nb"
# # print_dir_in_nb "$nb" --dir_name no_dir_and_dir --dir "$flag" >> "../tests/test_$flag_$nb_name.py"
# print_dir_in_nb "$nb" --dir_name no_dir_and_dir --dir "$flag" >> "../tests3/test_${flag}_$nb_name.py"
# done
# done

for nb in $nbs; do
# get name of notebook without extension
nb_name=$(basename "$nb" .ipynb)

# echo "Processing notebook: $nb"
# print_dir_in_nb "$nb" --dir_name no_dir_and_dir --dir "$flag" >> "../tests/test_$flag_$nb_name.py"
python cli.py "$nb" --dir_name get_all_tests2 >> "../tests/test_$nb_name.py"
done
Empty file added tests/__init__.py
Empty file.
51 changes: 51 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import logging
import os
import sys
import warnings

import pytest

from neuralforecast.tsdataset import TimeSeriesDataset
from neuralforecast.utils import AirPassengersDF as Y_df


@pytest.fixture(scope="session", autouse=True)
def setup_test_environment():
"""Configure the environment for all neural forecast tests."""
is_mac_ci = sys.platform.startswith('darwin') and os.getenv("CI", "false").lower() == "true"

if is_mac_ci:
# Disable memory cap (careful!) or force CPU mode
os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
os.environ["PYTORCH_MPS_HIGH_WATERMARK_RATIO"] = "0.0" # Removes MPS memory ceiling
os.environ["DEVICE"] = "cpu" # Optional: if your code uses this
logging.warning("Running on macOS CI – forcing MPS fallback settings")

logging.getLogger("pytorch_lightning").setLevel(logging.ERROR)
logging.getLogger("lightning_fabric").setLevel(logging.ERROR)
yield


@pytest.fixture
def suppress_warnings():
"""Suppress warnings for individual tests."""
with warnings.catch_warnings():
warnings.simplefilter("ignore")
yield


@pytest.fixture
def setup_dataset():
"""Setup train/test dataset for model testing."""
Y_train_df = Y_df[Y_df.ds <= "1959-12-31"] # 132 train
_ = Y_df[Y_df.ds > "1959-12-31"] # 12 test
dataset, *_ = TimeSeriesDataset.from_df(Y_train_df)
return dataset


@pytest.fixture
def full_dataset_split():
"""Provide both train and test dataframes if needed."""
Y_train_df = Y_df[Y_df.ds <= "1959-12-31"] # 132 train
Y_test_df = Y_df[Y_df.ds > "1959-12-31"] # 12 test
return Y_train_df, Y_test_df
Empty file added tests/test_common/__init__.py
Empty file.
Loading
Loading