Repository: Lightning-AI/pytorch-lightning
File: tests/tests_pytorch/callbacks/test_weight_averaging.py (Python)

Code before:
    # Test with epoch-based updates
    callback = EMAWeightAveraging(update_starting_at_epoch=2)

    assert not callback.should_update(epoch_idx=0)
    assert not callback.should_update(epoch_idx=1)
    assert callback.should_update(epoch_idx=2)
    assert callback.should_update(epoch_idx=3)


def test_ema_weight_averaging_checkpoint_save_load(tmp_path):
    """Test that EMAWeightAveraging correctly saves and loads checkpoints."""
    model = TestModel()
    model.crash_on_epoch = 2
    dataset = RandomDataset(32, 32)

    callback = EMAWeightAveraging(decay=0.99, update_every_n_steps=2)

    # Train and create checkpoint
    _train(model, dataset, tmp_path, callback, will_crash=True)

    # Resume from checkpoint
    model2 = TestModel()
    callback2 = EMAWeightAveraging(decay=0.99, update_every_n_steps=2)
    checkpoint_path = str(tmp_path / "lightning_logs" / "version_0" / "checkpoints" / "*.ckpt")

    _train(model2, dataset, tmp_path, callback2, checkpoint_path=checkpoint_path)

    assert callback2._average_model is not None


@pytest.mark.parametrize("decay", [0.9, 0.99, 0.999, 0.9999])
def test_ema_weight_averaging_decay_values(tmp_path, decay):
    """Test EMAWeightAveraging with different decay values."""
    model = TestModel()
    dataset = RandomDataset(32, 32)

    callback = EMAWeightAveraging(decay=decay, update_every_n_steps=1)
    _train(model, dataset, tmp_path, callback)

    assert callback._average_model is not None


Review comment (bug):
Hi @amorehead 

the checkpoint_path should actually be `tmp_path / "checkpoints" / "*.ckpt"`. Also, regex patterns aren’t supported for `checkpoint_path`, so we need to pass an existing file path instead.

```suggestion
    import glob   # should be at the top
    _train(model2, dataset, tmp_path, callback2,
           checkpoint_path=glob.glob((tmp_path / "checkpoints" / "*.ckpt").as_posix())[0])
```

I tested this locally — this should fix the failed test 🙂

Code after:
    # Test with epoch-based updates
    callback = EMAWeightAveraging(update_starting_at_epoch=2)

    assert not callback.should_update(epoch_idx=0)
    assert not callback.should_update(epoch_idx=1)
    assert callback.should_update(epoch_idx=2)
    assert callback.should_update(epoch_idx=3)


def test_ema_weight_averaging_checkpoint_save_load(tmp_path):
    """Test that EMAWeightAveraging correctly saves and loads checkpoints."""
    model = TestModel()
    model.crash_on_epoch = 2
    dataset = RandomDataset(32, 32)

    callback = EMAWeightAveraging(decay=0.99, update_every_n_steps=2)

    # Train and create checkpoint
    _train(model, dataset, tmp_path, callback, will_crash=True)

    # Resume from checkpoint
    model2 = TestModel()
    callback2 = EMAWeightAveraging(decay=0.99, update_every_n_steps=2)
    import glob  # should be at the top

    _train(
        model2,
        dataset,
        tmp_path,
        callback2,
        checkpoint_path=glob.glob((tmp_path / "checkpoints" / "*.ckpt").as_posix())[0],
    )

    assert callback2._average_model is not None


@pytest.mark.parametrize("decay", [0.9, 0.99, 0.999, 0.9999])
def test_ema_weight_averaging_decay_values(tmp_path, decay):
    """Test EMAWeightAveraging with different decay values."""
    model = TestModel()
    dataset = RandomDataset(32, 32)

    callback = EMAWeightAveraging(decay=decay, update_every_n_steps=1)
    _train(model, dataset, tmp_path, callback)

    assert callback._average_model is not None