diff --git a/lenskit-funksvd/tests/test_funksvd.py b/lenskit-funksvd/tests/test_funksvd.py
index bfa87121d..1e335cf64 100644
--- a/lenskit-funksvd/tests/test_funksvd.py
+++ b/lenskit-funksvd/tests/test_funksvd.py
@@ -13,9 +13,9 @@
 
 from pytest import approx, mark
 
-from lenskit.data.dataset import Dataset, from_interactions_df
 import lenskit.funksvd as svd
 import lenskit.util.test as lktu
+from lenskit.data.dataset import Dataset, from_interactions_df
 
 _log = logging.getLogger(__name__)
 
diff --git a/lenskit-hpf/tests/test_hpf.py b/lenskit-hpf/tests/test_hpf.py
index b5162c2ea..c49a3506a 100644
--- a/lenskit-hpf/tests/test_hpf.py
+++ b/lenskit-hpf/tests/test_hpf.py
@@ -12,9 +12,9 @@
 
 from pytest import importorskip, mark
 
-from lenskit.data.dataset import from_interactions_df
 import lenskit.util.test as lktu
 from lenskit.algorithms import basic
+from lenskit.data.dataset import from_interactions_df
 
 hpf = importorskip("lenskit.hpf")
 
diff --git a/lenskit-implicit/tests/test_implicit.py b/lenskit-implicit/tests/test_implicit.py
index 8f544881d..2edbe975c 100644
--- a/lenskit-implicit/tests/test_implicit.py
+++ b/lenskit-implicit/tests/test_implicit.py
@@ -12,9 +12,9 @@
 
 from pytest import mark
 
-from lenskit.data.dataset import from_interactions_df
 import lenskit.util.test as lktu
 from lenskit import util
+from lenskit.data.dataset import from_interactions_df
 from lenskit.implicit import ALS, BPR
 
 _log = logging.getLogger(__name__)
diff --git a/lenskit/tests/test_als_explicit.py b/lenskit/tests/test_als_explicit.py
index 0ef45a28e..55fc92bee 100644
--- a/lenskit/tests/test_als_explicit.py
+++ b/lenskit/tests/test_als_explicit.py
@@ -13,11 +13,11 @@
 
 from pytest import approx, mark
 
-from lenskit.data.dataset import Dataset, from_interactions_df
-from lenskit.data.movielens import load_movielens_df
 import lenskit.util.test as lktu
 from lenskit import batch
 from lenskit.algorithms import als
+from lenskit.data.dataset import Dataset, from_interactions_df
+from lenskit.data.movielens import load_movielens_df
 
 _log = logging.getLogger(__name__)
 
diff --git a/lenskit/tests/test_als_implicit.py b/lenskit/tests/test_als_implicit.py
index 37453f9a6..4d8a883b4 100644
--- a/lenskit/tests/test_als_implicit.py
+++ b/lenskit/tests/test_als_implicit.py
@@ -13,10 +13,10 @@
 
 from pytest import approx, mark
 
-from lenskit.data.dataset import Dataset, from_interactions_df
-from lenskit.data.movielens import load_movielens_df
 import lenskit.util.test as lktu
 from lenskit.algorithms import Recommender, als
+from lenskit.data.dataset import Dataset, from_interactions_df
+from lenskit.data.movielens import load_movielens_df
 
 _log = logging.getLogger(__name__)
 
diff --git a/lenskit/tests/test_batch_predict.py b/lenskit/tests/test_batch_predict.py
index ddd7dec12..23438fa11 100644
--- a/lenskit/tests/test_batch_predict.py
+++ b/lenskit/tests/test_batch_predict.py
@@ -13,10 +13,10 @@
 import pytest
 
 import lenskit.batch as lkb
-from lenskit.data.dataset import Dataset, from_interactions_df
 import lenskit.util.test as lktu
-from lenskit.util.test import ml_ratings, ml_ds  # noqa: F401
 from lenskit.algorithms.bias import Bias
+from lenskit.data.dataset import Dataset, from_interactions_df
+from lenskit.util.test import ml_ds, ml_ratings  # noqa: F401
 
 _log = logging.getLogger(__name__)
 
diff --git a/lenskit/tests/test_batch_recommend.py b/lenskit/tests/test_batch_recommend.py
index b3a693545..8f6092b82 100644
--- a/lenskit/tests/test_batch_recommend.py
+++ b/lenskit/tests/test_batch_recommend.py
@@ -13,12 +13,12 @@
 import pytest
 
 import lenskit.crossfold as xf
-from lenskit.data.dataset import Dataset, from_interactions_df
 import lenskit.util.test as lktu
 from lenskit import batch, topn
 from lenskit.algorithms import Recommender
 from lenskit.algorithms.basic import PopScore, TopN
 from lenskit.algorithms.bias import Bias
+from lenskit.data.dataset import Dataset, from_interactions_df
 
 _log = logging.getLogger(__name__)
 
diff --git a/lenskit/tests/test_bias.py b/lenskit/tests/test_bias.py
index 7cabc9181..5781f9197 100644
--- a/lenskit/tests/test_bias.py
+++ b/lenskit/tests/test_bias.py
@@ -9,9 +9,9 @@
 
 import numpy as np
 import pandas as pd
+import torch
 
 from pytest import approx, mark, raises
-import torch
 
 from lenskit import util as lku
 from lenskit.algorithms.bias import Bias
diff --git a/lenskit/tests/test_candidate_selector.py b/lenskit/tests/test_candidate_selector.py
index f158e77e8..3e0aa13b2 100644
--- a/lenskit/tests/test_candidate_selector.py
+++ b/lenskit/tests/test_candidate_selector.py
@@ -7,9 +7,9 @@
 import numpy as np
 import pandas as pd
 
-from lenskit.data.dataset import Dataset, from_interactions_df
 import lenskit.util.test as lktu
 from lenskit.algorithms import basic
+from lenskit.data.dataset import Dataset, from_interactions_df
 
 simple_df = pd.DataFrame(
     {"item": [1, 1, 2, 3], "user": [10, 12, 10, 13], "rating": [4.0, 3.0, 5.0, 2.0]}
diff --git a/lenskit/tests/test_crossfold.py b/lenskit/tests/test_crossfold.py
index ff512dd66..0f433b2d9 100644
--- a/lenskit/tests/test_crossfold.py
+++ b/lenskit/tests/test_crossfold.py
@@ -9,12 +9,11 @@
 import math
 
 import numpy as np
-
 import pandas as pd
+
 import pytest
 
 import lenskit.crossfold as xf
-import lenskit.util.test as lktu
 
 
 def test_partition_rows(ml_ratings: pd.DataFrame):
@@ -228,7 +227,7 @@ def test_partition_users(ml_ratings: pd.DataFrame):
 
 
 def test_partition_may_skip_train(ml_ratings: pd.DataFrame):
-    """Partitioning when users may not have enough ml_ratings to be in the train set and test set."""
+    "Partitioning when users may not have enough ratings to be in the train and test sets."
     # make a data set where some users only have 1 rating
     ml_ratings = ml_ratings.sample(frac=0.1)
     users = ml_ratings.groupby("user")["rating"].count()
diff --git a/lenskit/tests/test_dataset_lazy.py b/lenskit/tests/test_dataset_lazy.py
index 340afaaa2..e01bbbdc6 100644
--- a/lenskit/tests/test_dataset_lazy.py
+++ b/lenskit/tests/test_dataset_lazy.py
@@ -10,6 +10,7 @@
 
 import numpy as np
 import pandas as pd
+
 from pytest import approx
 
 from lenskit.data import Dataset
diff --git a/lenskit/tests/test_dataset_stats.py b/lenskit/tests/test_dataset_stats.py
index 7b7efc1c7..486c93878 100644
--- a/lenskit/tests/test_dataset_stats.py
+++ b/lenskit/tests/test_dataset_stats.py
@@ -10,6 +10,7 @@
 
 import numpy as np
 import pandas as pd
+
 from pytest import approx
 
 from lenskit.data import Dataset
diff --git a/lenskit/tests/test_fallback.py b/lenskit/tests/test_fallback.py
index 2a50edbd9..32f397ea6 100644
--- a/lenskit/tests/test_fallback.py
+++ b/lenskit/tests/test_fallback.py
@@ -11,12 +11,12 @@
 
 from pytest import approx
 
-from lenskit.data.dataset import Dataset
 import lenskit.util.test as lktu
 from lenskit import util as lku
 from lenskit.algorithms import basic
 from lenskit.algorithms.bias import Bias
-from lenskit.util.test import ml_ratings, ml_ds  # noqa: F401
+from lenskit.data.dataset import Dataset
+from lenskit.util.test import ml_ds, ml_ratings  # noqa: F401
 
 simple_df = pd.DataFrame(
     {"item": [1, 1, 2, 3], "user": [10, 12, 10, 13], "rating": [4.0, 3.0, 5.0, 2.0]}
diff --git a/lenskit/tests/test_knn_item_item.py b/lenskit/tests/test_knn_item_item.py
index e69ca3d16..3b46a16dc 100644
--- a/lenskit/tests/test_knn_item_item.py
+++ b/lenskit/tests/test_knn_item_item.py
@@ -17,17 +17,17 @@
 from pytest import approx, fixture, mark
 
 import lenskit.algorithms.knn.item as knn
-from lenskit.algorithms.ranking import TopN
-from lenskit.data.dataset import from_interactions_df
-from lenskit.data.vocab import EntityId, Vocabulary
 import lenskit.util.test as lktu
 from lenskit import batch
 from lenskit.algorithms import Recommender
 from lenskit.algorithms.basic import Fallback
 from lenskit.algorithms.bias import Bias
+from lenskit.algorithms.ranking import TopN
+from lenskit.data.dataset import from_interactions_df
+from lenskit.data.vocab import EntityId, Vocabulary
 from lenskit.diagnostics import ConfigWarning, DataWarning
 from lenskit.util import clone
-from lenskit.util.test import ml_ratings, ml_ds  # noqa: F401
+from lenskit.util.test import ml_ds, ml_ratings  # noqa: F401
 
 _log = logging.getLogger(__name__)
 
diff --git a/lenskit/tests/test_knn_user_user.py b/lenskit/tests/test_knn_user_user.py
index 6ce8932de..03786b660 100644
--- a/lenskit/tests/test_knn_user_user.py
+++ b/lenskit/tests/test_knn_user_user.py
@@ -15,12 +15,12 @@
 from pytest import approx, fail, mark
 
 import lenskit.algorithms.knn.user as knn
-from lenskit.algorithms.ranking import TopN
-from lenskit.data.dataset import Dataset, from_interactions_df
 import lenskit.util.test as lktu
 from lenskit.algorithms import Recommender
+from lenskit.algorithms.ranking import TopN
+from lenskit.data.dataset import Dataset, from_interactions_df
 from lenskit.util import clone
-from lenskit.util.test import ml_ratings, ml_ds  # noqa: F401
+from lenskit.util.test import ml_ds, ml_ratings  # noqa: F401
 
 _log = logging.getLogger(__name__)
 
diff --git a/lenskit/tests/test_load_movielens.py b/lenskit/tests/test_load_movielens.py
index a3773d482..1faeed537 100644
--- a/lenskit/tests/test_load_movielens.py
+++ b/lenskit/tests/test_load_movielens.py
@@ -4,12 +4,13 @@
 # Licensed under the MIT license, see LICENSE.md for details.
 # SPDX-License-Identifier: MIT
 
-from pathlib import Path
-from lenskit.data.movielens import load_movielens
 import functools
+from pathlib import Path
 
 from pytest import mark
 
+from lenskit.data.movielens import load_movielens
+
 ML_LATEST_DIR = Path("data/ml-latest-small")
 ML_100K_DIR = Path("data/ml-100k")
 ML_1M_DIR = Path("data/ml-1m")
diff --git a/lenskit/tests/test_popular.py b/lenskit/tests/test_popular.py
index af9458d6f..bbba6d4db 100644
--- a/lenskit/tests/test_popular.py
+++ b/lenskit/tests/test_popular.py
@@ -9,8 +9,8 @@
 import pandas as pd
 
 import lenskit.util.test as lktu
-from lenskit.util.test import ml_ratings, ml_ds  # noqa: F401
 from lenskit.algorithms import basic
+from lenskit.util.test import ml_ds, ml_ratings  # noqa: F401
 
 simple_df = pd.DataFrame(
     {"item": [1, 1, 2, 3], "user": [10, 12, 10, 13], "rating": [4.0, 3.0, 5.0, 2.0]}
diff --git a/lenskit/tests/test_predict_metrics.py b/lenskit/tests/test_predict_metrics.py
index 18ad019d9..346951cb7 100644
--- a/lenskit/tests/test_predict_metrics.py
+++ b/lenskit/tests/test_predict_metrics.py
@@ -9,9 +9,9 @@
 
 from pytest import approx, mark, raises
 
-from lenskit.data.dataset import from_interactions_df
 import lenskit.metrics.predict as pm
 import lenskit.util.test as lktu
+from lenskit.data.dataset import from_interactions_df
 
 
 def test_check_missing_empty():
diff --git a/lenskit/tests/test_rerank.py b/lenskit/tests/test_rerank.py
index 7af8b7999..f073f2a7b 100644
--- a/lenskit/tests/test_rerank.py
+++ b/lenskit/tests/test_rerank.py
@@ -8,7 +8,7 @@
 from lenskit.algorithms.basic import PopScore
 from lenskit.algorithms.bias import Bias
 from lenskit.algorithms.ranking import PlackettLuce
-from lenskit.util.test import ml_ratings, ml_ds  # noqa: F401
+from lenskit.util.test import ml_ds, ml_ratings  # noqa: F401
 
 
 def test_plackett_luce_rec(ml_ds):
diff --git a/lenskit/tests/test_svd.py b/lenskit/tests/test_svd.py
index b183565f5..6a76c1c71 100644
--- a/lenskit/tests/test_svd.py
+++ b/lenskit/tests/test_svd.py
@@ -12,9 +12,8 @@
 
 from pytest import approx, mark
 
-from lenskit.data.dataset import Dataset, from_interactions_df
-import lenskit.util.test as lktu
 from lenskit.algorithms import svd
+from lenskit.data.dataset import Dataset, from_interactions_df
 from lenskit.util import clone
 
 _log = logging.getLogger(__name__)
diff --git a/lenskit/tests/test_topn_recs.py b/lenskit/tests/test_topn_recs.py
index 1e00b0d61..b12058ec1 100644
--- a/lenskit/tests/test_topn_recs.py
+++ b/lenskit/tests/test_topn_recs.py
@@ -9,9 +9,9 @@
 
 from pytest import approx
 
-from lenskit.data.dataset import Dataset, from_interactions_df
 import lenskit.util.test as lktu
 from lenskit.algorithms import basic, bias
+from lenskit.data.dataset import Dataset, from_interactions_df
 
 simple_df = pd.DataFrame(
     {"item": [1, 1, 2, 3], "user": [10, 12, 10, 13], "rating": [4.0, 3.0, 5.0, 2.0]}
diff --git a/lenskit/tests/test_util_algos.py b/lenskit/tests/test_util_algos.py
index fea9804ca..363a8ffa8 100644
--- a/lenskit/tests/test_util_algos.py
+++ b/lenskit/tests/test_util_algos.py
@@ -7,10 +7,10 @@
 import numpy as np
 import pandas as pd
 
-from lenskit.data.dataset import Dataset, from_interactions_df
 import lenskit.util.test as lktu
 from lenskit.algorithms import basic
-from lenskit.util.test import ml_ratings, ml_ds  # noqa: F401
+from lenskit.data.dataset import Dataset, from_interactions_df
+from lenskit.util.test import ml_ds, ml_ratings  # noqa: F401
 
 simple_df = pd.DataFrame(
     {"item": [1, 1, 2, 3], "user": [10, 12, 10, 13], "rating": [4.0, 3.0, 5.0, 2.0]}
diff --git a/lenskit/tests/test_vocab.py b/lenskit/tests/test_vocab.py
index 02baabf63..1eb5fe3b3 100644
--- a/lenskit/tests/test_vocab.py
+++ b/lenskit/tests/test_vocab.py
@@ -10,9 +10,10 @@
 
 from uuid import UUID
 
+import numpy as np
+
 import hypothesis.strategies as st
 from hypothesis import assume, given
-import numpy as np
 from pytest import raises
 
 from lenskit.data import Vocabulary
@@ -59,7 +60,6 @@ def test_create_nonunique(keys: list[int | str | UUID]):
     )
 )
 def test_equal(keys: list[int | str | UUID]):
-    uq = set(keys)
     vocab = Vocabulary(keys)
 
     v2 = Vocabulary(keys)
@@ -210,7 +210,6 @@ def test_add_terms(initial: set[int], new: list[int]):
 
 @given(st.one_of(st.sets(st.integers()), st.sets(st.emails())))
 def test_all_terms(initial: set[int] | set[str]):
-    ni = len(initial)
     vocab = Vocabulary(initial)
 
     tl = sorted(initial)