Repository: narwhals-dev/narwhals
Pull request #1827 (2025-01-19 15:13:32)

feat: Deprecate Expr.arg_true (but keep Series.arg_true, and keep both available in stable.v1)
Similar to #1791 

This one both changes length and is order-dependent. Plus, it's currently only being tested for eager backends anyway. Best to clean it up

The only usage we have in the wild of it is Formulaic where they do `Series.arg_true`, where I can indeed see it being useful

<!--
# Thanks for contributing a pull request! 
## Please make sure you see our contribution guidelines: https://github.com/narwhals-dev/narwhals/blob/main/CONTRIBUTING.md
-->

## What type of PR is this? (check all applicable)

- [ ] 💾 Refactor
- [ ] ✨ Feature
- [ ] 🐛 Bug Fix
- [ ] 🔧 Optimization
- [ ] 📝 Documentation
- [ ] ✅ Test
- [ ] 🐳 Other

## Related issues

- Related issue #\<issue number\>
- Closes #\<issue number\>

## Checklist

- [ ] Code follows style guide (ruff)
- [ ] Tests added
- [ ] Documented the changes

## If you have comments or can explain your changes, please do so below



Patch:
diff --git a/narwhals/_arrow/namespace.py b/narwhals/_arrow/namespace.py
index 70d372a5..e1ad9550 100644
--- a/narwhals/_arrow/namespace.py
+++ b/narwhals/_arrow/namespace.py
@@ -441,7 +441,7 @@ class ArrowWhen:
         except TypeError:
             # `self._then_value` is a scalar and can't be converted to an expression
             value_series = plx._create_series_from_scalar(
-                self._then_value, reference_series=condition
+                self._then_value, reference_series=condition.alias("literal")
             )
 
         condition_native, value_series_native = broadcast_series(
diff --git a/narwhals/_dask/namespace.py b/narwhals/_dask/namespace.py
index 936b9abb..485163a0 100644
--- a/narwhals/_dask/namespace.py
+++ b/narwhals/_dask/namespace.py
@@ -411,8 +411,8 @@ class DaskWhen:
 
         if is_scalar:
             _df = condition.to_frame("a")
-            _df["tmp"] = value_sequence[0]
-            value_series = _df["tmp"]
+            _df["literal"] = value_sequence[0]
+            value_series = _df["literal"]
         else:
             value_series = value_sequence
 
diff --git a/narwhals/_duckdb/expr_dt.py b/narwhals/_duckdb/expr_dt.py
index c3ed9710..fa8e0c61 100644
--- a/narwhals/_duckdb/expr_dt.py
+++ b/narwhals/_duckdb/expr_dt.py
@@ -130,3 +130,55 @@ class DuckDBExprDateTimeNamespace:
             "date",
             returns_scalar=self._compliant_expr._returns_scalar,
         )
+
+    def total_minutes(self) -> DuckDBExpr:
+        from duckdb import ConstantExpression
+        from duckdb import FunctionExpression
+
+        return self._compliant_expr._from_call(
+            lambda _input: FunctionExpression(
+                "datepart", ConstantExpression("minute"), _input
+            ),
+            "total_minutes",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def total_seconds(self) -> DuckDBExpr:
+        from duckdb import ConstantExpression
+        from duckdb import FunctionExpression
+
+        return self._compliant_expr._from_call(
+            lambda _input: 60
+            * FunctionExpression("datepart", ConstantExpression("minute"), _input)
+            + FunctionExpression("datepart", ConstantExpression("second"), _input),
+            "total_seconds",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def total_milliseconds(self) -> DuckDBExpr:
+        from duckdb import ConstantExpression
+        from duckdb import FunctionExpression
+
+        return self._compliant_expr._from_call(
+            lambda _input: 60_000
+            * FunctionExpression("datepart", ConstantExpression("minute"), _input)
+            + FunctionExpression("datepart", ConstantExpression("millisecond"), _input),
+            "total_milliseconds",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def total_microseconds(self) -> DuckDBExpr:
+        from duckdb import ConstantExpression
+        from duckdb import FunctionExpression
+
+        return self._compliant_expr._from_call(
+            lambda _input: 60_000_000
+            * FunctionExpression("datepart", ConstantExpression("minute"), _input)
+            + FunctionExpression("datepart", ConstantExpression("microsecond"), _input),
+            "total_microseconds",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def total_nanoseconds(self) -> DuckDBExpr:
+        msg = "`total_nanoseconds` is not implemented for DuckDB"
+        raise NotImplementedError(msg)
diff --git a/narwhals/_duckdb/namespace.py b/narwhals/_duckdb/namespace.py
index c91d11d3..c516336c 100644
--- a/narwhals/_duckdb/namespace.py
+++ b/narwhals/_duckdb/namespace.py
@@ -248,22 +248,27 @@ class DuckDBWhen:
             value = parse_into_expr(self._then_value, namespace=plx)(df)[0]
         except TypeError:
             # `self._otherwise_value` is a scalar and can't be converted to an expression
-            value = ConstantExpression(self._then_value)
+            value = ConstantExpression(self._then_value).alias("literal")
         value = cast("duckdb.Expression", value)
+        value_name = get_column_name(df, value)
 
         if self._otherwise_value is None:
-            return [CaseExpression(condition=condition, value=value)]
+            return [CaseExpression(condition=condition, value=value).alias(value_name)]
         try:
             otherwise_expr = parse_into_expr(self._otherwise_value, namespace=plx)
         except TypeError:
             # `self._otherwise_value` is a scalar and can't be converted to an expression
             return [
-                CaseExpression(condition=condition, value=value).otherwise(
-                    ConstantExpression(self._otherwise_value)
-                )
+                CaseExpression(condition=condition, value=value)
+                .otherwise(ConstantExpression(self._otherwise_value))
+                .alias(value_name)
             ]
         otherwise = otherwise_expr(df)[0]
-        return [CaseExpression(condition=condition, value=value).otherwise(otherwise)]
+        return [
+            CaseExpression(condition=condition, value=value)
+            .otherwise(otherwise)
+            .alias(value_name)
+        ]
 
     def then(self, value: DuckDBExpr | Any) -> DuckDBThen:
         self._then_value = value
diff --git a/narwhals/_pandas_like/namespace.py b/narwhals/_pandas_like/namespace.py
index 4265a340..84efef83 100644
--- a/narwhals/_pandas_like/namespace.py
+++ b/narwhals/_pandas_like/namespace.py
@@ -467,13 +467,12 @@ class PandasWhen:
         except TypeError:
             # `self._then_value` is a scalar and can't be converted to an expression
             value_series = plx._create_series_from_scalar(
-                self._then_value, reference_series=condition
+                self._then_value, reference_series=condition.alias("literal")
             )
 
         condition_native, value_series_native = broadcast_align_and_extract_native(
             condition, value_series
         )
-
         if self._otherwise_value is None:
             return [
                 value_series._from_native_series(
diff --git a/narwhals/_pandas_like/utils.py b/narwhals/_pandas_like/utils.py
index 159a9f1c..28b7a903 100644
--- a/narwhals/_pandas_like/utils.py
+++ b/narwhals/_pandas_like/utils.py
@@ -128,7 +128,7 @@ def broadcast_align_and_extract_native(
             s = rhs._native_series
             return (
                 lhs._native_series,
-                s.__class__(s.iloc[0], index=lhs_index, dtype=s.dtype),
+                s.__class__(s.iloc[0], index=lhs_index, dtype=s.dtype, name=rhs.name),
             )
         if lhs.len() == 1:
             # broadcast
diff --git a/narwhals/_spark_like/expr.py b/narwhals/_spark_like/expr.py
index 98a1d2d5..ba063c64 100644
--- a/narwhals/_spark_like/expr.py
+++ b/narwhals/_spark_like/expr.py
@@ -7,6 +7,7 @@ from typing import Literal
 from typing import Sequence
 
 from narwhals._expression_parsing import infer_new_root_output_names
+from narwhals._spark_like.expr_dt import SparkLikeExprDateTimeNamespace
 from narwhals._spark_like.expr_name import SparkLikeExprNameNamespace
 from narwhals._spark_like.expr_str import SparkLikeExprStringNamespace
 from narwhals._spark_like.utils import get_column_name
@@ -541,3 +542,7 @@ class SparkLikeExpr(CompliantExpr["Column"]):
     @property
     def name(self: Self) -> SparkLikeExprNameNamespace:
         return SparkLikeExprNameNamespace(self)
+
+    @property
+    def dt(self: Self) -> SparkLikeExprDateTimeNamespace:
+        return SparkLikeExprDateTimeNamespace(self)
diff --git a/narwhals/_spark_like/expr_dt.py b/narwhals/_spark_like/expr_dt.py
new file mode 100644
index 00000000..4c31d6b6
--- /dev/null
+++ b/narwhals/_spark_like/expr_dt.py
@@ -0,0 +1,135 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+    from pyspark.sql import Column
+    from typing_extensions import Self
+
+    from narwhals._spark_like.expr import SparkLikeExpr
+
+
+class SparkLikeExprDateTimeNamespace:
+    def __init__(self: Self, expr: SparkLikeExpr) -> None:
+        self._compliant_expr = expr
+
+    def date(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        return self._compliant_expr._from_call(
+            F.to_date,
+            "date",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def year(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        return self._compliant_expr._from_call(
+            F.year,
+            "year",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def month(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        return self._compliant_expr._from_call(
+            F.month,
+            "month",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def day(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        return self._compliant_expr._from_call(
+            F.dayofmonth,
+            "day",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def hour(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        return self._compliant_expr._from_call(
+            F.hour,
+            "hour",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def minute(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        return self._compliant_expr._from_call(
+            F.minute,
+            "minute",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def second(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        return self._compliant_expr._from_call(
+            F.second,
+            "second",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def millisecond(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        def _millisecond(_input: Column) -> Column:
+            return F.floor((F.unix_micros(_input) % 1_000_000) / 1000)
+
+        return self._compliant_expr._from_call(
+            _millisecond,
+            "millisecond",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def microsecond(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        def _microsecond(_input: Column) -> Column:
+            return F.unix_micros(_input) % 1_000_000
+
+        return self._compliant_expr._from_call(
+            _microsecond,
+            "microsecond",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def nanosecond(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        def _nanosecond(_input: Column) -> Column:
+            return (F.unix_micros(_input) % 1_000_000) * 1000
+
+        return self._compliant_expr._from_call(
+            _nanosecond,
+            "nanosecond",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def ordinal_day(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        return self._compliant_expr._from_call(
+            F.dayofyear,
+            "ordinal_day",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+    def weekday(self: Self) -> SparkLikeExpr:
+        from pyspark.sql import functions as F  # noqa: N812
+
+        def _weekday(_input: Column) -> Column:
+            # PySpark's dayofweek returns 1-7 for Sunday-Saturday
+            return (F.dayofweek(_input) + 6) % 7
+
+        return self._compliant_expr._from_call(
+            _weekday,
+            "weekday",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
diff --git a/narwhals/_spark_like/expr_str.py b/narwhals/_spark_like/expr_str.py
index 2bb6d300..06af832a 100644
--- a/narwhals/_spark_like/expr_str.py
+++ b/narwhals/_spark_like/expr_str.py
@@ -1,6 +1,7 @@
 from __future__ import annotations
 
 from typing import TYPE_CHECKING
+from typing import overload
 
 if TYPE_CHECKING:
     from pyspark.sql import Column
@@ -128,3 +129,56 @@ class SparkLikeExprStringNamespace:
             "to_lowercase",
             returns_scalar=self._compliant_expr._returns_scalar,
         )
+
+    def to_datetime(self: Self, format: str | None) -> SparkLikeExpr:  # noqa: A002
+        from pyspark.sql import functions as F  # noqa: N812
+
+        return self._compliant_expr._from_call(
+            lambda _input: F.to_timestamp(
+                F.replace(_input, F.lit("T"), F.lit(" ")),
+                format=strptime_to_pyspark_format(format),
+            ),
+            "to_datetime",
+            returns_scalar=self._compliant_expr._returns_scalar,
+        )
+
+
+@overload
+def strptime_to_pyspark_format(format: None) -> None: ...
+
+
+@overload
+def strptime_to_pyspark_format(format: str) -> str: ...
+
+
+def strptime_to_pyspark_format(format: str | None) -> str | None:  # noqa: A002
+    """Converts a Python strptime datetime format string to a PySpark datetime format string."""
+    # Mapping from Python strptime format to PySpark format
+    if format is None:
+        return None
+
+    # see https://spark.apache.org/docs/latest/sql-ref-datetime-pattern.html
+    # and https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
+    format_mapping = {
+        "%Y": "y",  # Year with century
+        "%y": "y",  # Year without century
+        "%m": "M",  # Month
+        "%d": "d",  # Day of the month
+        "%H": "H",  # Hour (24-hour clock) 0-23
+        "%I": "h",  # Hour (12-hour clock) 1-12
+        "%M": "m",  # Minute
+        "%S": "s",  # Second
+        "%f": "S",  # Microseconds -> Milliseconds
+        "%p": "a",  # AM/PM
+        "%a": "E",  # Abbreviated weekday name
+        "%A": "E",  # Full weekday name
+        "%j": "D",  # Day of the year
+        "%z": "Z",  # Timezone offset
+        "%s": "X",  # Unix timestamp
+    }
+
+    # Replace Python format specifiers with PySpark specifiers
+    pyspark_format = format
+    for py_format, spark_format in format_mapping.items():
+        pyspark_format = pyspark_format.replace(py_format, spark_format)
+    return pyspark_format.replace("T", " ")
diff --git a/narwhals/expr.py b/narwhals/expr.py
index 69c2e7dc..4d17552a 100644
--- a/narwhals/expr.py
+++ b/narwhals/expr.py
@@ -2206,50 +2206,13 @@ class Expr:
 
         Returns:
             A new expression.
-
-        Examples:
-            >>> import pandas as pd
-            >>> import polars as pl
-            >>> import pyarrow as pa
-            >>> import narwhals as nw
-            >>> from narwhals.typing import IntoFrameT
-            >>>
-            >>> data = {"a": [1, None, None, 2]}
-            >>> df_pd = pd.DataFrame(data)
-            >>> df_pl = pl.DataFrame(data)
-            >>> df_pa = pa.table(data)
-
-            We define a library agnostic function:
-
-            >>> def agnostic_arg_true(df_native: IntoFrameT) -> IntoFrameT:
-            ...     df = nw.from_native(df_native)
-            ...     return df.select(nw.col("a").is_null().arg_true()).to_native()
-
-            We can then pass any supported library such as pandas, Polars, or
-            PyArrow to `agnostic_arg_true`:
-
-            >>> agnostic_arg_true(df_pd)
-               a
-            1  1
-            2  2
-
-            >>> agnostic_arg_true(df_pl)
-            shape: (2, 1)
-            ┌─────┐
-            │ a   │
-            │ --- │
-            │ u32 │
-            ╞═════╡
-            │ 1   │
-            │ 2   │
-            └─────┘
-
-            >>> agnostic_arg_true(df_pa)
-            pyarrow.Table
-            a: int64
-            ----
-            a: [[1,2]]
         """
+        msg = (
+            "`Expr.arg_true` is deprecated and will be removed in a future version.\n\n"
+            "Note: this will remain available in `narwhals.stable.v1`.\n"
+            "See https://narwhals-dev.github.io/narwhals/backcompat/ for more information.\n"
+        )
+        issue_deprecation_warning(msg, _version="1.23.0")
         return self.__class__(
             lambda plx: self._to_compliant_expr(plx).arg_true(), is_order_dependent=True
         )
diff --git a/narwhals/stable/v1/__init__.py b/narwhals/stable/v1/__init__.py
index 941f1637..76dee2e4 100644
--- a/narwhals/stable/v1/__init__.py
+++ b/narwhals/stable/v1/__init__.py
@@ -920,6 +920,16 @@ class Expr(NwExpr):
             is_order_dependent=True,
         )
 
+    def arg_true(self) -> Self:
+        """Find elements where boolean expression is True.
+
+        Returns:
+            A new expression.
+        """
+        return self.__class__(
+            lambda plx: self._to_compliant_expr(plx).arg_true(), is_order_dependent=True
+        )
+
     def sample(
         self: Self,
         n: int | None = None,


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
index 95b969e9..eeb1f1a8 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -2,6 +2,7 @@ from __future__ import annotations
 
 import os
 import sys
+from copy import deepcopy
 from typing import TYPE_CHECKING
 from typing import Any
 from typing import Callable
@@ -12,6 +13,8 @@ import polars as pl
 import pyarrow as pa
 import pytest
 
+from narwhals.utils import generate_temporary_column_name
+
 if TYPE_CHECKING:
     import duckdb
 
@@ -67,64 +70,66 @@ def pytest_collection_modifyitems(
             item.add_marker(skip_slow)
 
 
-def pandas_constructor(obj: Any) -> IntoDataFrame:
+def pandas_constructor(obj: dict[str, list[Any]]) -> IntoDataFrame:
     return pd.DataFrame(obj)  # type: ignore[no-any-return]
 
 
-def pandas_nullable_constructor(obj: Any) -> IntoDataFrame:
+def pandas_nullable_constructor(obj: dict[str, list[Any]]) -> IntoDataFrame:
     return pd.DataFrame(obj).convert_dtypes(dtype_backend="numpy_nullable")  # type: ignore[no-any-return]
 
 
-def pandas_pyarrow_constructor(obj: Any) -> IntoDataFrame:
+def pandas_pyarrow_constructor(obj: dict[str, list[Any]]) -> IntoDataFrame:
     return pd.DataFrame(obj).convert_dtypes(dtype_backend="pyarrow")  # type: ignore[no-any-return]
 
 
-def modin_constructor(obj: Any) -> IntoDataFrame:  # pragma: no cover
+def modin_constructor(obj: dict[str, list[Any]]) -> IntoDataFrame:  # pragma: no cover
     import modin.pandas as mpd
 
     return mpd.DataFrame(pd.DataFrame(obj))  # type: ignore[no-any-return]
 
 
-def modin_pyarrow_constructor(obj: Any) -> IntoDataFrame:  # pragma: no cover
+def modin_pyarrow_constructor(
+    obj: dict[str, list[Any]],
+) -> IntoDataFrame:  # pragma: no cover
     import modin.pandas as mpd
 
     return mpd.DataFrame(pd.DataFrame(obj)).convert_dtypes(dtype_backend="pyarrow")  # type: ignore[no-any-return]
 
 
-def cudf_constructor(obj: Any) -> IntoDataFrame:  # pragma: no cover
+def cudf_constructor(obj: dict[str, list[Any]]) -> IntoDataFrame:  # pragma: no cover
     import cudf
 
     return cudf.DataFrame(obj)  # type: ignore[no-any-return]
 
 
-def polars_eager_constructor(obj: Any) -> IntoDataFrame:
+def polars_eager_constructor(obj: dict[str, list[Any]]) -> IntoDataFrame:
     return pl.DataFrame(obj)
 
 
-def polars_lazy_constructor(obj: Any) -> pl.LazyFrame:
+def polars_lazy_constructor(obj: dict[str, list[Any]]) -> pl.LazyFrame:
     return pl.LazyFrame(obj)
 
 
-def duckdb_lazy_constructor(obj: Any) -> duckdb.DuckDBPyRelation:
+def duckdb_lazy_constructor(obj: dict[str, list[Any]]) -> duckdb.DuckDBPyRelation:
     import duckdb
 
     _df = pl.LazyFrame(obj)
     return duckdb.table("_df")
 
 
-def dask_lazy_p1_constructor(obj: Any) -> IntoFrame:  # pragma: no cover
+def dask_lazy_p1_constructor(obj: dict[str, list[Any]]) -> IntoFrame:  # pragma: no cover
     import dask.dataframe as dd
 
     return dd.from_dict(obj, npartitions=1)  # type: ignore[no-any-return]
 
 
-def dask_lazy_p2_constructor(obj: Any) -> IntoFrame:  # pragma: no cover
+def dask_lazy_p2_constructor(obj: dict[str, list[Any]]) -> IntoFrame:  # pragma: no cover
     import dask.dataframe as dd
 
     return dd.from_dict(obj, npartitions=2)  # type: ignore[no-any-return]
 
 
-def pyarrow_table_constructor(obj: Any) -> IntoDataFrame:
+def pyarrow_table_constructor(obj: dict[str, list[Any]]) -> IntoDataFrame:
     return pa.table(obj)  # type: ignore[no-any-return]
 
 
@@ -159,13 +164,16 @@ def pyspark_lazy_constructor() -> Callable[[Any], IntoFrame]:  # pragma: no cove
 
         register(session.stop)
 
-        def _constructor(obj: Any) -> IntoFrame:
-            pd_df = pd.DataFrame(obj).replace({float("nan"): None}).reset_index()
+        def _constructor(obj: dict[str, list[Any]]) -> IntoFrame:
+            _obj = deepcopy(obj)
+            index_col_name = generate_temporary_column_name(n_bytes=8, columns=list(_obj))
+            _obj[index_col_name] = list(range(len(_obj[next(iter(_obj))])))
+
             return (  # type: ignore[no-any-return]
-                session.createDataFrame(pd_df)
+                session.createDataFrame([*zip(*_obj.values())], schema=[*_obj.keys()])
                 .repartition(2)
-                .orderBy("index")
-                .drop("index")
+                .orderBy(index_col_name)
+                .drop(index_col_name)
             )
 
         return _constructor
diff --git a/tests/expr_and_series/arg_max_test.py b/tests/expr_and_series/arg_max_test.py
index 45b1ad06..9f9de077 100644
--- a/tests/expr_and_series/arg_max_test.py
+++ b/tests/expr_and_series/arg_max_test.py
@@ -6,7 +6,7 @@ import narwhals.stable.v1 as nw
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9], "i": [3, 1, 5]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "i": [3, 1, 5]}
 
 
 def test_expr_arg_max_expr(
diff --git a/tests/expr_and_series/arg_min_test.py b/tests/expr_and_series/arg_min_test.py
index 1654f6fe..406e80c2 100644
--- a/tests/expr_and_series/arg_min_test.py
+++ b/tests/expr_and_series/arg_min_test.py
@@ -6,7 +6,7 @@ import narwhals.stable.v1 as nw
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
 
 
 def test_expr_arg_min_expr(
diff --git a/tests/expr_and_series/arg_true_test.py b/tests/expr_and_series/arg_true_test.py
index 6db10dab..ec7d1d88 100644
--- a/tests/expr_and_series/arg_true_test.py
+++ b/tests/expr_and_series/arg_true_test.py
@@ -2,21 +2,21 @@ from __future__ import annotations
 
 import pytest
 
-import narwhals.stable.v1 as nw
+import narwhals as nw
+import narwhals.stable.v1 as nw_v1
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
 
-def test_arg_true(
-    constructor_eager: ConstructorEager, request: pytest.FixtureRequest
-) -> None:
-    if "dask" in str(constructor_eager):
-        request.applymarker(pytest.mark.xfail)
-    df = nw.from_native(constructor_eager({"a": [1, None, None, 3]}))
-    result = df.select(nw.col("a").is_null().arg_true())
+def test_arg_true(constructor_eager: ConstructorEager) -> None:
+    df = nw_v1.from_native(constructor_eager({"a": [1, None, None, 3]}))
+    result = df.select(nw_v1.col("a").is_null().arg_true())
     expected = {"a": [1, 2]}
     assert_equal_data(result, expected)
 
+    with pytest.deprecated_call():
+        df.select(nw.col("a").is_null().arg_true())
+
 
 def test_arg_true_series(constructor_eager: ConstructorEager) -> None:
     df = nw.from_native(constructor_eager({"a": [1, None, None, 3]}), eager_only=True)
diff --git a/tests/expr_and_series/arithmetic_test.py b/tests/expr_and_series/arithmetic_test.py
index 1baae44e..3a5cde3a 100644
--- a/tests/expr_and_series/arithmetic_test.py
+++ b/tests/expr_and_series/arithmetic_test.py
@@ -45,7 +45,7 @@ def test_arithmetic_expr(
     ):
         request.applymarker(pytest.mark.xfail)
 
-    data = {"a": [1.0, 2, 3]}
+    data = {"a": [1.0, 2.0, 3.0]}
     df = nw.from_native(constructor(data))
     result = df.select(getattr(nw.col("a"), attr)(rhs))
     assert_equal_data(result, {"a": expected})
@@ -57,7 +57,7 @@ def test_arithmetic_expr(
         ("__radd__", 1, [2, 3, 4]),
         ("__rsub__", 1, [0, -1, -2]),
         ("__rmul__", 2, [2, 4, 6]),
-        ("__rtruediv__", 2.0, [2, 1, 2 / 3]),
+        ("__rtruediv__", 2.0, [2.0, 1.0, 2 / 3]),
         ("__rfloordiv__", 2, [2, 1, 0]),
         ("__rmod__", 2, [0, 0, 2]),
         ("__rpow__", 2, [2, 4, 8]),
@@ -119,7 +119,7 @@ def test_arithmetic_series(
         ("__radd__", 1, [2, 3, 4]),
         ("__rsub__", 1, [0, -1, -2]),
         ("__rmul__", 2, [2, 4, 6]),
-        ("__rtruediv__", 2.0, [2, 1, 2 / 3]),
+        ("__rtruediv__", 2.0, [2.0, 1.0, 2 / 3]),
         ("__rfloordiv__", 2, [2, 1, 0]),
         ("__rmod__", 2, [0, 0, 2]),
         ("__rpow__", 2, [2, 4, 8]),
@@ -231,7 +231,7 @@ def test_mod(left: int, right: int) -> None:
         ("__add__", nw.lit(1), [2, 3, 5]),
         ("__sub__", nw.lit(1), [0, -1, -3]),
         ("__mul__", nw.lit(2), [2, 4, 8]),
-        ("__truediv__", nw.lit(2.0), [2, 1, 0.5]),
+        ("__truediv__", nw.lit(2.0), [2.0, 1.0, 0.5]),
         ("__truediv__", nw.lit(1), [1, 0.5, 0.25]),
         ("__floordiv__", nw.lit(2), [2, 1, 0]),
         ("__mod__", nw.lit(3), [0, 1, 3]),
@@ -254,7 +254,7 @@ def test_arithmetic_expr_left_literal(
     ):
         request.applymarker(pytest.mark.xfail)
 
-    data = {"a": [1.0, 2, 4]}
+    data = {"a": [1.0, 2.0, 4.0]}
     df = nw.from_native(constructor(data))
     result = df.select(getattr(lhs, attr)(nw.col("a")))
     assert_equal_data(result, {"literal": expected})
@@ -266,8 +266,8 @@ def test_arithmetic_expr_left_literal(
         ("__add__", nw.lit(1), [2, 3, 5]),
         ("__sub__", nw.lit(1), [0, -1, -3]),
         ("__mul__", nw.lit(2), [2, 4, 8]),
-        ("__truediv__", nw.lit(2.0), [2, 1, 0.5]),
-        ("__truediv__", nw.lit(1), [1, 0.5, 0.25]),
+        ("__truediv__", nw.lit(2.0), [2.0, 1.0, 0.5]),
+        ("__truediv__", nw.lit(1), [1.0, 0.5, 0.25]),
         ("__floordiv__", nw.lit(2), [2, 1, 0]),
         ("__mod__", nw.lit(3), [0, 1, 3]),
         ("__pow__", nw.lit(2), [2, 4, 16]),
@@ -285,7 +285,7 @@ def test_arithmetic_series_left_literal(
     ):
         request.applymarker(pytest.mark.xfail)
 
-    data = {"a": [1.0, 2, 4]}
+    data = {"a": [1.0, 2.0, 4.0]}
     df = nw.from_native(constructor_eager(data))
     result = df.select(getattr(lhs, attr)(nw.col("a")))
     assert_equal_data(result, {"literal": expected})
diff --git a/tests/expr_and_series/binary_test.py b/tests/expr_and_series/binary_test.py
index 308745cb..6f8e8670 100644
--- a/tests/expr_and_series/binary_test.py
+++ b/tests/expr_and_series/binary_test.py
@@ -13,7 +13,7 @@ def test_expr_binary(constructor: Constructor, request: pytest.FixtureRequest) -
         constructor
     ):
         request.applymarker(pytest.mark.xfail)
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df_raw = constructor(data)
     result = nw.from_native(df_raw).with_columns(
         a=(1 + 3 * nw.col("a")) * (1 / nw.col("a")),
diff --git a/tests/expr_and_series/double_selected_test.py b/tests/expr_and_series/double_selected_test.py
index 9eb91892..a99c9016 100644
--- a/tests/expr_and_series/double_selected_test.py
+++ b/tests/expr_and_series/double_selected_test.py
@@ -6,7 +6,7 @@ from tests.utils import assert_equal_data
 
 
 def test_double_selected(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7, 8, 9]}
     df = nw.from_native(constructor(data))
 
     result = df.select(nw.col("a", "b") * 2)
diff --git a/tests/expr_and_series/double_test.py b/tests/expr_and_series/double_test.py
index 6f43ad13..df988ab1 100644
--- a/tests/expr_and_series/double_test.py
+++ b/tests/expr_and_series/double_test.py
@@ -6,7 +6,7 @@ from tests.utils import assert_equal_data
 
 
 def test_double(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.with_columns(nw.all() * 2)
     expected = {"a": [2, 6, 4], "b": [8, 8, 12], "z": [14.0, 16.0, 18.0]}
@@ -14,7 +14,7 @@ def test_double(constructor: Constructor) -> None:
 
 
 def test_double_alias(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.with_columns(nw.col("a").alias("o"), nw.all() * 2)
     expected = {
diff --git a/tests/expr_and_series/dt/datetime_attributes_test.py b/tests/expr_and_series/dt/datetime_attributes_test.py
index b1d09406..3c8a16b7 100644
--- a/tests/expr_and_series/dt/datetime_attributes_test.py
+++ b/tests/expr_and_series/dt/datetime_attributes_test.py
@@ -49,8 +49,6 @@ def test_datetime_attributes(
         request.applymarker(pytest.mark.xfail)
     if attribute == "date" and "cudf" in str(constructor):
         request.applymarker(pytest.mark.xfail)
-    if "pyspark" in str(constructor):
-        request.applymarker(pytest.mark.xfail)
 
     df = nw.from_native(constructor(data))
     result = df.select(getattr(nw.col("a").dt, attribute)())
diff --git a/tests/expr_and_series/dt/datetime_duration_test.py b/tests/expr_and_series/dt/datetime_duration_test.py
index 7ec281da..32bf5d90 100644
--- a/tests/expr_and_series/dt/datetime_duration_test.py
+++ b/tests/expr_and_series/dt/datetime_duration_test.py
@@ -46,7 +46,9 @@ def test_duration_attributes(
 ) -> None:
     if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(constructor):
         request.applymarker(pytest.mark.xfail)
-    if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
+    if "pyspark" in str(constructor):
+        request.applymarker(pytest.mark.xfail)
+    if "duckdb" in str(constructor) and attribute == "total_nanoseconds":
         request.applymarker(pytest.mark.xfail)
 
     df = nw.from_native(constructor(data))
diff --git a/tests/expr_and_series/fill_null_test.py b/tests/expr_and_series/fill_null_test.py
index 39b0a3c6..97f93768 100644
--- a/tests/expr_and_series/fill_null_test.py
+++ b/tests/expr_and_series/fill_null_test.py
@@ -16,9 +16,9 @@ def test_fill_null(request: pytest.FixtureRequest, constructor: Constructor) ->
     if "pyspark" in str(constructor):
         request.applymarker(pytest.mark.xfail)
     data = {
-        "a": [0.0, None, 2, 3, 4],
-        "b": [1.0, None, None, 5, 3],
-        "c": [5.0, None, 3, 2, 1],
+        "a": [0.0, None, 2.0, 3.0, 4.0],
+        "b": [1.0, None, None, 5.0, 3.0],
+        "c": [5.0, None, 3.0, 2.0, 1.0],
     }
     df = nw.from_native(constructor(data))
 
@@ -33,7 +33,7 @@ def test_fill_null(request: pytest.FixtureRequest, constructor: Constructor) ->
 
 def test_fill_null_exceptions(constructor: Constructor) -> None:
     data = {
-        "a": [0.0, None, 2, 3, 4],
+        "a": [0.0, None, 2.0, 3.0, 4.0],
     }
     df = nw.from_native(constructor(data))
 
diff --git a/tests/expr_and_series/is_duplicated_test.py b/tests/expr_and_series/is_duplicated_test.py
index d97d30cb..fe8b45bf 100644
--- a/tests/expr_and_series/is_duplicated_test.py
+++ b/tests/expr_and_series/is_duplicated_test.py
@@ -11,7 +11,7 @@ from tests.utils import assert_equal_data
 def test_is_duplicated_expr(
     constructor: Constructor, request: pytest.FixtureRequest
 ) -> None:
-    if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
+    if "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
     data = {"a": [1, 1, 2], "b": [1, 2, 3], "index": [0, 1, 2]}
     df = nw.from_native(constructor(data))
@@ -23,7 +23,7 @@ def test_is_duplicated_expr(
 def test_is_duplicated_w_nulls_expr(
     constructor: Constructor, request: pytest.FixtureRequest
 ) -> None:
-    if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
+    if "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
     data = {"a": [1, 1, None], "b": [1, None, None], "index": [0, 1, 2]}
     df = nw.from_native(constructor(data))
diff --git a/tests/expr_and_series/is_unique_test.py b/tests/expr_and_series/is_unique_test.py
index 92e72562..3e9259c0 100644
--- a/tests/expr_and_series/is_unique_test.py
+++ b/tests/expr_and_series/is_unique_test.py
@@ -9,7 +9,7 @@ from tests.utils import assert_equal_data
 
 
 def test_is_unique_expr(constructor: Constructor, request: pytest.FixtureRequest) -> None:
-    if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
+    if "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
     data = {
         "a": [1, 1, 2],
@@ -29,7 +29,7 @@ def test_is_unique_expr(constructor: Constructor, request: pytest.FixtureRequest
 def test_is_unique_w_nulls_expr(
     constructor: Constructor, request: pytest.FixtureRequest
 ) -> None:
-    if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
+    if "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
     data = {
         "a": [None, 1, 2],
diff --git a/tests/expr_and_series/lit_test.py b/tests/expr_and_series/lit_test.py
index f24e6d4a..b29ab89e 100644
--- a/tests/expr_and_series/lit_test.py
+++ b/tests/expr_and_series/lit_test.py
@@ -29,7 +29,7 @@ def test_lit(
 ) -> None:
     if "pyspark" in str(constructor) and dtype is not None:
         request.applymarker(pytest.mark.xfail)
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df_raw = constructor(data)
     df = nw.from_native(df_raw).lazy()
     result = df.with_columns(nw.lit(2, dtype).alias("lit"))
@@ -43,7 +43,7 @@ def test_lit(
 
 
 def test_lit_error(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df_raw = constructor(data)
     df = nw.from_native(df_raw).lazy()
     with pytest.raises(
diff --git a/tests/expr_and_series/max_test.py b/tests/expr_and_series/max_test.py
index 09483cb7..f2a31961 100644
--- a/tests/expr_and_series/max_test.py
+++ b/tests/expr_and_series/max_test.py
@@ -7,7 +7,7 @@ from tests.utils import Constructor
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
 
 
 @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").max(), nw.max("a", "b", "z")])
diff --git a/tests/expr_and_series/mean_test.py b/tests/expr_and_series/mean_test.py
index bab1fe82..6e5ce59a 100644
--- a/tests/expr_and_series/mean_test.py
+++ b/tests/expr_and_series/mean_test.py
@@ -7,7 +7,7 @@ from tests.utils import Constructor
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 7], "z": [7.0, 8, 9]}
+data = {"a": [1, 3, 2], "b": [4, 4, 7], "z": [7.0, 8.0, 9.0]}
 
 
 @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").mean(), nw.mean("a", "b", "z")])
diff --git a/tests/expr_and_series/median_test.py b/tests/expr_and_series/median_test.py
index 9c509a18..a548754b 100644
--- a/tests/expr_and_series/median_test.py
+++ b/tests/expr_and_series/median_test.py
@@ -11,7 +11,7 @@ from tests.utils import assert_equal_data
 data = {
     "a": [3, 8, 2, None],
     "b": [5, 5, None, 7],
-    "z": [7.0, 8, 9, None],
+    "z": [7.0, 8.0, 9.0, None],
     "s": ["f", "a", "x", "x"],
 }
 
diff --git a/tests/expr_and_series/min_test.py b/tests/expr_and_series/min_test.py
index f50facb3..1ed0fa2a 100644
--- a/tests/expr_and_series/min_test.py
+++ b/tests/expr_and_series/min_test.py
@@ -7,7 +7,7 @@ from tests.utils import Constructor
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
 
 
 @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").min(), nw.min("a", "b", "z")])
diff --git a/tests/expr_and_series/n_unique_test.py b/tests/expr_and_series/n_unique_test.py
index 1bcbe89f..c761b20f 100644
--- a/tests/expr_and_series/n_unique_test.py
+++ b/tests/expr_and_series/n_unique_test.py
@@ -7,7 +7,7 @@ from tests.utils import assert_equal_data
 
 data = {
     "a": [1.0, None, None, 3.0],
-    "b": [1.0, None, 4, 5.0],
+    "b": [1.0, None, 4.0, 5.0],
 }
 
 
diff --git a/tests/expr_and_series/nth_test.py b/tests/expr_and_series/nth_test.py
index a7dc7f64..d2fc79b0 100644
--- a/tests/expr_and_series/nth_test.py
+++ b/tests/expr_and_series/nth_test.py
@@ -8,7 +8,7 @@ from tests.utils import POLARS_VERSION
 from tests.utils import Constructor
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8, 9]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}
 
 
 @pytest.mark.parametrize(
@@ -16,7 +16,7 @@ data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8, 9]}
     [
         (0, {"a": [1, 3, 2]}),
         ([0, 1], {"a": [1, 3, 2], "b": [4, 4, 6]}),
-        ([0, 2], {"a": [1, 3, 2], "z": [7.1, 8, 9]}),
+        ([0, 2], {"a": [1, 3, 2], "z": [7.1, 8.0, 9.0]}),
     ],
 )
 def test_nth(
diff --git a/tests/expr_and_series/null_count_test.py b/tests/expr_and_series/null_count_test.py
index db162363..5a07f29b 100644
--- a/tests/expr_and_series/null_count_test.py
+++ b/tests/expr_and_series/null_count_test.py
@@ -7,7 +7,7 @@ from tests.utils import assert_equal_data
 
 data = {
     "a": [1.0, None, None, 3.0],
-    "b": [1.0, None, 4, 5.0],
+    "b": [1.0, None, 4.0, 5.0],
 }
 
 
diff --git a/tests/expr_and_series/quantile_test.py b/tests/expr_and_series/quantile_test.py
index a9207ceb..b18d112c 100644
--- a/tests/expr_and_series/quantile_test.py
+++ b/tests/expr_and_series/quantile_test.py
@@ -35,7 +35,7 @@ def test_quantile_expr(
         request.applymarker(pytest.mark.xfail)
 
     q = 0.3
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df_raw = constructor(data)
     df = nw.from_native(df_raw)
 
@@ -71,7 +71,7 @@ def test_quantile_series(
 ) -> None:
     q = 0.3
 
-    series = nw.from_native(constructor_eager({"a": [7.0, 8, 9]}), eager_only=True)[
+    series = nw.from_native(constructor_eager({"a": [7.0, 8.0, 9.0]}), eager_only=True)[
         "a"
     ].alias("a")
     result = series.quantile(quantile=q, interpolation=interpolation)
diff --git a/tests/expr_and_series/std_test.py b/tests/expr_and_series/std_test.py
index f2eabf4f..0cc9b672 100644
--- a/tests/expr_and_series/std_test.py
+++ b/tests/expr_and_series/std_test.py
@@ -9,8 +9,8 @@ from tests.utils import Constructor
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
-data_with_nulls = {"a": [1, 3, 2, None], "b": [4, 4, 6, None], "z": [7.0, 8, 9, None]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
+data_with_nulls = {"a": [1, 3, 2, None], "b": [4, 4, 6, None], "z": [7.0, 8.0, 9.0, None]}
 
 expected_results = {
     "a_ddof_1": [1.0],
diff --git a/tests/expr_and_series/str/to_datetime_test.py b/tests/expr_and_series/str/to_datetime_test.py
index bfb2a4df..99f886a1 100644
--- a/tests/expr_and_series/str/to_datetime_test.py
+++ b/tests/expr_and_series/str/to_datetime_test.py
@@ -18,7 +18,7 @@ data = {"a": ["2020-01-01T12:34:56"]}
 
 
 def test_to_datetime(constructor: Constructor, request: pytest.FixtureRequest) -> None:
-    if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
+    if "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
     if "cudf" in str(constructor):
         expected = "2020-01-01T12:34:56.000000000"
@@ -80,7 +80,9 @@ def test_to_datetime_infer_fmt(
         request.applymarker(pytest.mark.xfail)
     if "cudf" in str(constructor):
         expected = expected_cudf
-    if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
+    if "duckdb" in str(constructor):
+        request.applymarker(pytest.mark.xfail)
+    if "pyspark" in str(constructor) and data["a"][0] == "20240101123456":
         request.applymarker(pytest.mark.xfail)
     result = (
         nw.from_native(constructor(data))
@@ -133,7 +135,7 @@ def test_to_datetime_series_infer_fmt(
 def test_to_datetime_infer_fmt_from_date(
     constructor: Constructor, request: pytest.FixtureRequest
 ) -> None:
-    if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
+    if "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
     data = {"z": ["2020-01-01", "2020-01-02", None]}
     expected = [datetime(2020, 1, 1), datetime(2020, 1, 2), None]
diff --git a/tests/expr_and_series/sum_horizontal_test.py b/tests/expr_and_series/sum_horizontal_test.py
index decb65c0..8b3dcf56 100644
--- a/tests/expr_and_series/sum_horizontal_test.py
+++ b/tests/expr_and_series/sum_horizontal_test.py
@@ -15,7 +15,7 @@ def test_sumh(
 ) -> None:
     if "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.with_columns(horizontal_sum=nw.sum_horizontal(col_expr, nw.col("b")))
     expected = {
diff --git a/tests/expr_and_series/sum_test.py b/tests/expr_and_series/sum_test.py
index f988e899..8f3ce950 100644
--- a/tests/expr_and_series/sum_test.py
+++ b/tests/expr_and_series/sum_test.py
@@ -7,7 +7,7 @@ from tests.utils import Constructor
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
 
 
 @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").sum(), nw.sum("a", "b", "z")])
diff --git a/tests/expr_and_series/unary_test.py b/tests/expr_and_series/unary_test.py
index 51d8c636..618a477d 100644
--- a/tests/expr_and_series/unary_test.py
+++ b/tests/expr_and_series/unary_test.py
@@ -17,7 +17,7 @@ def test_unary(constructor: Constructor, request: pytest.FixtureRequest) -> None
         "a": [1, 3, 2],
         "b": [4, 4, 6],
         "c": [7.0, 8.0, None],
-        "z": [7.0, 8, 9],
+        "z": [7.0, 8.0, 9.0],
     }
     result = nw.from_native(constructor(data)).select(
         a_mean=nw.col("a").mean(),
@@ -49,7 +49,7 @@ def test_unary_series(constructor_eager: ConstructorEager) -> None:
         "a": [1, 3, 2],
         "b": [4, 4, 6],
         "c": [7.0, 8.0, None],
-        "z": [7.0, 8, 9],
+        "z": [7.0, 8.0, 9.0],
     }
     df = nw.from_native(constructor_eager(data), eager_only=True)
     result = {
diff --git a/tests/expr_and_series/var_test.py b/tests/expr_and_series/var_test.py
index 2053dfe6..0edd8e30 100644
--- a/tests/expr_and_series/var_test.py
+++ b/tests/expr_and_series/var_test.py
@@ -9,8 +9,8 @@ from tests.utils import Constructor
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
-data_with_nulls = {"a": [1, 3, 2, None], "b": [4, 4, 6, None], "z": [7.0, 8, 9, None]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
+data_with_nulls = {"a": [1, 3, 2, None], "b": [4, 4, 6, None], "z": [7.0, 8.0, 9.0, None]}
 
 expected_results = {
     "a_ddof_1": [1.0],
diff --git a/tests/expr_and_series/when_test.py b/tests/expr_and_series/when_test.py
index 4f768db0..140626e4 100644
--- a/tests/expr_and_series/when_test.py
+++ b/tests/expr_and_series/when_test.py
@@ -24,6 +24,11 @@ def test_when(constructor: Constructor) -> None:
         "a_when": [3, None, None],
     }
     assert_equal_data(result, expected)
+    result = df.select(nw.when(nw.col("a") == 1).then(value=3))
+    expected = {
+        "literal": [3, None, None],
+    }
+    assert_equal_data(result, expected)
 
 
 def test_when_otherwise(constructor: Constructor) -> None:
@@ -121,22 +126,14 @@ def test_otherwise_expression(constructor: Constructor) -> None:
     assert_equal_data(result, expected)
 
 
-def test_when_then_otherwise_into_expr(
-    constructor: Constructor, request: pytest.FixtureRequest
-) -> None:
-    if "duckdb" in str(constructor):
-        request.applymarker(pytest.mark.xfail)
+def test_when_then_otherwise_into_expr(constructor: Constructor) -> None:
     df = nw.from_native(constructor(data))
     result = df.select(nw.when(nw.col("a") > 1).then("c").otherwise("e"))
     expected = {"c": [7, 5, 6]}
     assert_equal_data(result, expected)
 
 
-def test_when_then_otherwise_lit_str(
-    constructor: Constructor, request: pytest.FixtureRequest
-) -> None:
-    if "duckdb" in str(constructor):
-        request.applymarker(pytest.mark.xfail)
+def test_when_then_otherwise_lit_str(constructor: Constructor) -> None:
     df = nw.from_native(constructor(data))
     result = df.select(nw.when(nw.col("a") > 1).then(nw.col("b")).otherwise(nw.lit("z")))
     expected = {"b": ["z", "b", "c"]}
diff --git a/tests/frame/add_test.py b/tests/frame/add_test.py
index e0456189..ec152f85 100644
--- a/tests/frame/add_test.py
+++ b/tests/frame/add_test.py
@@ -10,7 +10,7 @@ from tests.utils import assert_equal_data
 def test_add(constructor: Constructor, request: pytest.FixtureRequest) -> None:
     if "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.with_columns(
         c=nw.col("a") + nw.col("b"),
diff --git a/tests/frame/columns_test.py b/tests/frame/columns_test.py
index 3a18fb59..d3b3af34 100644
--- a/tests/frame/columns_test.py
+++ b/tests/frame/columns_test.py
@@ -12,7 +12,7 @@ if TYPE_CHECKING:
 
 @pytest.mark.filterwarnings("ignore:Determining|Resolving.*")
 def test_columns(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.columns
     expected = ["a", "b", "z"]
diff --git a/tests/frame/concat_test.py b/tests/frame/concat_test.py
index e38f4f4f..bbdd306f 100644
--- a/tests/frame/concat_test.py
+++ b/tests/frame/concat_test.py
@@ -12,7 +12,7 @@ def test_concat_horizontal(
 ) -> None:
     if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df_left = nw.from_native(constructor(data)).lazy()
 
     data_right = {"c": [6, 12, -1], "d": [0, -4, 2]}
@@ -22,7 +22,7 @@ def test_concat_horizontal(
     expected = {
         "a": [1, 3, 2],
         "b": [4, 4, 6],
-        "z": [7.0, 8, 9],
+        "z": [7.0, 8.0, 9.0],
         "c": [6, 12, -1],
         "d": [0, -4, 2],
     }
@@ -33,7 +33,7 @@ def test_concat_horizontal(
 
 
 def test_concat_vertical(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df_left = (
         nw.from_native(constructor(data)).lazy().rename({"a": "c", "b": "d"}).drop("z")
     )
diff --git a/tests/frame/double_test.py b/tests/frame/double_test.py
index a99cef5e..93884b9d 100644
--- a/tests/frame/double_test.py
+++ b/tests/frame/double_test.py
@@ -6,7 +6,7 @@ from tests.utils import assert_equal_data
 
 
 def test_double(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
 
     result = df.with_columns(nw.all() * 2)
diff --git a/tests/frame/drop_test.py b/tests/frame/drop_test.py
index eb9bb266..2ef3b4f4 100644
--- a/tests/frame/drop_test.py
+++ b/tests/frame/drop_test.py
@@ -24,7 +24,7 @@ if TYPE_CHECKING:
     ],
 )
 def test_drop(constructor: Constructor, to_drop: list[str], expected: list[str]) -> None:
-    data = {"abc": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"abc": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     assert df.drop(to_drop).collect_schema().names() == expected
     if not isinstance(to_drop, str):
diff --git a/tests/frame/filter_test.py b/tests/frame/filter_test.py
index 922af0e6..579d4013 100644
--- a/tests/frame/filter_test.py
+++ b/tests/frame/filter_test.py
@@ -12,7 +12,7 @@ from tests.utils import assert_equal_data
 
 
 def test_filter(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.filter(nw.col("a") > 1)
     expected = {"a": [3, 2], "b": [4, 6], "z": [8.0, 9.0]}
@@ -24,7 +24,7 @@ def test_filter_with_boolean_list(
 ) -> None:
     if "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     context = (
         pytest.raises(TypeError, match="not supported")
@@ -38,7 +38,7 @@ def test_filter_with_boolean_list(
 
 
 def test_filter_raise_on_agg_predicate(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
 
     context = (
@@ -56,7 +56,7 @@ def test_filter_raise_on_agg_predicate(constructor: Constructor) -> None:
 
 
 def test_filter_raise_on_shape_mismatch(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
 
     context = (
diff --git a/tests/frame/head_test.py b/tests/frame/head_test.py
index e817aa41..09b36b07 100644
--- a/tests/frame/head_test.py
+++ b/tests/frame/head_test.py
@@ -6,7 +6,7 @@ from tests.utils import assert_equal_data
 
 
 def test_head(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     expected = {"a": [1, 3], "b": [4, 4], "z": [7.0, 8.0]}
 
     df_raw = constructor(data)
diff --git a/tests/frame/invalid_test.py b/tests/frame/invalid_test.py
index 5d2f7b45..967481f3 100644
--- a/tests/frame/invalid_test.py
+++ b/tests/frame/invalid_test.py
@@ -10,7 +10,7 @@ from tests.utils import NUMPY_VERSION
 
 
 def test_invalid() -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(pa.table({"a": [1, 2], "b": [3, 4]}))
     with pytest.raises(ValueError, match="Multi-output"):
         df.select(nw.all() + nw.all())
diff --git a/tests/frame/is_duplicated_test.py b/tests/frame/is_duplicated_test.py
index bcc80371..481fb772 100644
--- a/tests/frame/is_duplicated_test.py
+++ b/tests/frame/is_duplicated_test.py
@@ -6,7 +6,7 @@ from tests.utils import assert_equal_data
 
 
 def test_is_duplicated(constructor_eager: ConstructorEager) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df_raw = constructor_eager(data)
     df = nw.from_native(df_raw, eager_only=True)
     result = nw.concat([df, df.head(1)]).is_duplicated()
diff --git a/tests/frame/is_empty_test.py b/tests/frame/is_empty_test.py
index 7ea6b22a..47c347af 100644
--- a/tests/frame/is_empty_test.py
+++ b/tests/frame/is_empty_test.py
@@ -15,7 +15,7 @@ if TYPE_CHECKING:
 def test_is_empty(
     constructor_eager: ConstructorEager, threshold: Any, expected: Any
 ) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df_raw = constructor_eager(data)
     df = nw.from_native(df_raw, eager_only=True)
     result = df.filter(nw.col("a") > threshold).is_empty()
diff --git a/tests/frame/is_unique_test.py b/tests/frame/is_unique_test.py
index 81718f36..88dacd01 100644
--- a/tests/frame/is_unique_test.py
+++ b/tests/frame/is_unique_test.py
@@ -6,7 +6,7 @@ from tests.utils import assert_equal_data
 
 
 def test_is_unique(constructor_eager: ConstructorEager) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df_raw = constructor_eager(data)
     df = nw.from_native(df_raw, eager_only=True)
     result = nw.concat([df, df.head(1)]).is_unique()
diff --git a/tests/frame/item_test.py b/tests/frame/item_test.py
index 5a5f037f..3646c203 100644
--- a/tests/frame/item_test.py
+++ b/tests/frame/item_test.py
@@ -20,7 +20,7 @@ def test_item(
     column: int | str | None,
     expected: Any,
 ) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor_eager(data), eager_only=True)
     assert_equal_data({"a": [df.item(row, column)]}, {"a": [expected]})
     assert_equal_data({"a": [df.select("a").head(1).item()]}, {"a": [1]})
@@ -52,6 +52,6 @@ def test_item_value_error(
     column: int | str | None,
     err_msg: str,
 ) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     with pytest.raises(ValueError, match=err_msg):
         nw.from_native(constructor_eager(data), eager_only=True).item(row, column)
diff --git a/tests/frame/join_test.py b/tests/frame/join_test.py
index 4c3c1419..68e2ed8b 100644
--- a/tests/frame/join_test.py
+++ b/tests/frame/join_test.py
@@ -21,7 +21,7 @@ def test_inner_join_two_keys(constructor: Constructor) -> None:
     data = {
         "antananarivo": [1, 3, 2],
         "bob": [4, 4, 6],
-        "zor ro": [7.0, 8, 9],
+        "zor ro": [7.0, 8.0, 9.0],
         "idx": [0, 1, 2],
     }
     df = nw_main.from_native(constructor(data))
@@ -38,9 +38,9 @@ def test_inner_join_two_keys(constructor: Constructor) -> None:
     expected = {
         "antananarivo": [1, 3, 2],
         "bob": [4, 4, 6],
-        "zor ro": [7.0, 8, 9],
+        "zor ro": [7.0, 8.0, 9.0],
         "idx": [0, 1, 2],
-        "zor ro_right": [7.0, 8, 9],
+        "zor ro_right": [7.0, 8.0, 9.0],
     }
     assert_equal_data(result, expected)
     assert_equal_data(result_on, expected)
@@ -50,7 +50,7 @@ def test_inner_join_single_key(constructor: Constructor) -> None:
     data = {
         "antananarivo": [1, 3, 2],
         "bob": [4, 4, 6],
-        "zor ro": [7.0, 8, 9],
+        "zor ro": [7.0, 8.0, 9.0],
         "idx": [0, 1, 2],
     }
     df = nw.from_native(constructor(data))
@@ -67,10 +67,10 @@ def test_inner_join_single_key(constructor: Constructor) -> None:
     expected = {
         "antananarivo": [1, 3, 2],
         "bob": [4, 4, 6],
-        "zor ro": [7.0, 8, 9],
+        "zor ro": [7.0, 8.0, 9.0],
         "idx": [0, 1, 2],
         "bob_right": [4, 4, 6],
-        "zor ro_right": [7.0, 8, 9],
+        "zor ro_right": [7.0, 8.0, 9.0],
     }
     assert_equal_data(result, expected)
     assert_equal_data(result_on, expected)
@@ -100,7 +100,7 @@ def test_suffix(constructor: Constructor, how: str, suffix: str) -> None:
     data = {
         "antananarivo": [1, 3, 2],
         "bob": [4, 4, 6],
-        "zor ro": [7.0, 8, 9],
+        "zor ro": [7.0, 8.0, 9.0],
     }
     df = nw.from_native(constructor(data))
     df_right = df
@@ -168,7 +168,7 @@ def test_anti_join(
     filter_expr: nw.Expr,
     expected: dict[str, list[Any]],
 ) -> None:
-    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8, 9]}
+    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     other = df.filter(filter_expr)
     result = df.join(other, how="anti", left_on=join_key, right_on=join_key)  # type: ignore[arg-type]
@@ -206,7 +206,7 @@ def test_semi_join(
     filter_expr: nw.Expr,
     expected: dict[str, list[Any]],
 ) -> None:
-    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8, 9]}
+    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     other = df.filter(filter_expr)
     result = df.join(other, how="semi", left_on=join_key, right_on=join_key).sort(  # type: ignore[arg-type]
@@ -217,7 +217,7 @@ def test_semi_join(
 
 @pytest.mark.parametrize("how", ["right", "full"])
 def test_join_not_implemented(constructor: Constructor, how: str) -> None:
-    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8, 9]}
+    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
 
     with pytest.raises(
@@ -231,13 +231,13 @@ def test_join_not_implemented(constructor: Constructor, how: str) -> None:
 
 def test_left_join(constructor: Constructor) -> None:
     data_left = {
-        "antananarivo": [1.0, 2, 3],
-        "bob": [4.0, 5, 6],
+        "antananarivo": [1.0, 2.0, 3.0],
+        "bob": [4.0, 5.0, 6.0],
         "idx": [0.0, 1.0, 2.0],
     }
     data_right = {
-        "antananarivo": [1.0, 2, 3],
-        "co": [4.0, 5, 7],
+        "antananarivo": [1.0, 2.0, 3.0],
+        "co": [4.0, 5.0, 7.0],
         "idx": [0.0, 1.0, 2.0],
     }
     df_left = nw.from_native(constructor(data_left))
@@ -286,15 +286,15 @@ def test_left_join_multiple_column(constructor: Constructor) -> None:
 
 def test_left_join_overlapping_column(constructor: Constructor) -> None:
     data_left = {
-        "antananarivo": [1.0, 2, 3],
-        "bob": [4.0, 5, 6],
-        "d": [1.0, 4, 2],
+        "antananarivo": [1.0, 2.0, 3.0],
+        "bob": [4.0, 5.0, 6.0],
+        "d": [1.0, 4.0, 2.0],
         "idx": [0.0, 1.0, 2.0],
     }
     data_right = {
-        "antananarivo": [1.0, 2, 3],
-        "c": [4.0, 5, 6],
-        "d": [1.0, 4, 2],
+        "antananarivo": [1.0, 2.0, 3.0],
+        "c": [4.0, 5.0, 6.0],
+        "d": [1.0, 4.0, 2.0],
         "idx": [0.0, 1.0, 2.0],
     }
     df_left = nw.from_native(constructor(data_left))
@@ -331,7 +331,7 @@ def test_left_join_overlapping_column(constructor: Constructor) -> None:
 
 @pytest.mark.parametrize("how", ["inner", "left", "semi", "anti"])
 def test_join_keys_exceptions(constructor: Constructor, how: str) -> None:
-    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8, 9]}
+    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
 
     with pytest.raises(
@@ -536,7 +536,7 @@ def test_joinasof_by(
 def test_joinasof_not_implemented(
     constructor: Constructor, strategy: Literal["backward", "forward"]
 ) -> None:
-    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8, 9]}
+    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
 
     with pytest.raises(
@@ -552,7 +552,7 @@ def test_joinasof_not_implemented(
 
 
 def test_joinasof_keys_exceptions(constructor: Constructor) -> None:
-    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8, 9]}
+    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
 
     with pytest.raises(
@@ -593,7 +593,7 @@ def test_joinasof_keys_exceptions(constructor: Constructor) -> None:
 
 
 def test_joinasof_by_exceptions(constructor: Constructor) -> None:
-    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8, 9]}
+    data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     with pytest.raises(
         ValueError,
diff --git a/tests/frame/reindex_test.py b/tests/frame/reindex_test.py
index e31ca936..6cad175c 100644
--- a/tests/frame/reindex_test.py
+++ b/tests/frame/reindex_test.py
@@ -8,7 +8,7 @@ import pytest
 import narwhals.stable.v1 as nw
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
 
 
 @pytest.mark.parametrize("df_raw", [pd.DataFrame(data)])
diff --git a/tests/frame/rename_test.py b/tests/frame/rename_test.py
index 24c04620..ccc832eb 100644
--- a/tests/frame/rename_test.py
+++ b/tests/frame/rename_test.py
@@ -6,8 +6,8 @@ from tests.utils import assert_equal_data
 
 
 def test_rename(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.rename({"a": "x", "b": "y"})
-    expected = {"x": [1, 3, 2], "y": [4, 4, 6], "z": [7.0, 8, 9]}
+    expected = {"x": [1, 3, 2], "y": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     assert_equal_data(result, expected)
diff --git a/tests/frame/rows_test.py b/tests/frame/rows_test.py
index cdf42648..a2a70f46 100644
--- a/tests/frame/rows_test.py
+++ b/tests/frame/rows_test.py
@@ -11,7 +11,7 @@ import narwhals.stable.v1 as nw
 if TYPE_CHECKING:
     from tests.utils import ConstructorEager
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
 data_na = {"a": [None, 3, 2], "b": [4, 4, 6], "z": [7.0, None, 9]}
 
 
@@ -38,7 +38,7 @@ def test_iter_rows(
     if "cudf" in str(constructor_eager):
         request.applymarker(pytest.mark.xfail)
 
-    data = {"a": [1, 3, 2], "_b": [4, 4, 6], "z": [7.0, 8, 9], "1": [5, 6, 7]}
+    data = {"a": [1, 3, 2], "_b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "1": [5, 6, 7]}
     df = nw.from_native(constructor_eager(data), eager_only=True)
     result = list(df.iter_rows(named=named))
     assert result == expected
@@ -94,7 +94,7 @@ def test_rows_eager(
     expected: list[tuple[Any, ...]] | list[dict[str, Any]],
 ) -> None:
     # posit-dev/py-shiny relies on `.rows(named=False)` to return unnamed rows
-    data = {"a": [1, 3, 2], "_b": [4, 4, 6], "z": [7.0, 8, 9], "1": [5, 6, 7]}
+    data = {"a": [1, 3, 2], "_b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "1": [5, 6, 7]}
     df = nw.from_native(constructor_eager(data), eager_only=True)
     result = df.rows(named=named)
     assert result == expected
diff --git a/tests/frame/schema_test.py b/tests/frame/schema_test.py
index 565bf015..9b395aaa 100644
--- a/tests/frame/schema_test.py
+++ b/tests/frame/schema_test.py
@@ -27,7 +27,9 @@ data = {
 
 @pytest.mark.filterwarnings("ignore:Determining|Resolving.*")
 def test_schema(constructor: Constructor) -> None:
-    df = nw.from_native(constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8, 9]}))
+    df = nw.from_native(
+        constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]})
+    )
     result = df.schema
     expected = {"a": nw.Int64, "b": nw.Int64, "z": nw.Float64}
 
@@ -38,7 +40,9 @@ def test_schema(constructor: Constructor) -> None:
 
 
 def test_collect_schema(constructor: Constructor) -> None:
-    df = nw.from_native(constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8, 9]}))
+    df = nw.from_native(
+        constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]})
+    )
     expected = {"a": nw.Int64, "b": nw.Int64, "z": nw.Float64}
 
     result = df.collect_schema()
diff --git a/tests/frame/select_test.py b/tests/frame/select_test.py
index 946e5820..3593eed2 100644
--- a/tests/frame/select_test.py
+++ b/tests/frame/select_test.py
@@ -20,7 +20,7 @@ class Foo: ...
 
 
 def test_select(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.select("a")
     expected = {"a": [1, 3, 2]}
@@ -82,7 +82,7 @@ def test_missing_columns(
 ) -> None:
     if ("pyspark" in str(constructor)) or "duckdb" in str(constructor):
         request.applymarker(pytest.mark.xfail)
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     selected_columns = ["a", "e", "f"]
     msg = (
diff --git a/tests/frame/sort_test.py b/tests/frame/sort_test.py
index 1ce3414c..5833b5cc 100644
--- a/tests/frame/sort_test.py
+++ b/tests/frame/sort_test.py
@@ -8,7 +8,7 @@ from tests.utils import assert_equal_data
 
 
 def test_sort(constructor: Constructor) -> None:
-    data = {"an tan": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"an tan": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.sort("an tan", "b")
     expected = {
diff --git a/tests/frame/tail_test.py b/tests/frame/tail_test.py
index 75f46a4a..c261477f 100644
--- a/tests/frame/tail_test.py
+++ b/tests/frame/tail_test.py
@@ -13,7 +13,7 @@ def test_tail(request: pytest.FixtureRequest, constructor: Constructor) -> None:
     if "pyspark" in str(constructor):
         request.applymarker(pytest.mark.xfail)
 
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     expected = {"a": [3, 2], "b": [4, 6], "z": [8.0, 9]}
 
     df_raw = constructor(data)
diff --git a/tests/frame/to_arrow_test.py b/tests/frame/to_arrow_test.py
index 70913ed1..651dfaba 100644
--- a/tests/frame/to_arrow_test.py
+++ b/tests/frame/to_arrow_test.py
@@ -21,7 +21,7 @@ def test_to_arrow(
         # pyarrow requires pandas>=1.0.0
         request.applymarker(pytest.mark.xfail)
 
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}
     df_raw = constructor_eager(data)
     result = nw.from_native(df_raw, eager_only=True).to_arrow()
 
diff --git a/tests/frame/to_dict_test.py b/tests/frame/to_dict_test.py
index e6a434b7..fa31a7a7 100644
--- a/tests/frame/to_dict_test.py
+++ b/tests/frame/to_dict_test.py
@@ -11,14 +11,14 @@ from tests.utils import assert_equal_data
     "ignore:.*all arguments of to_dict except for the argument:FutureWarning"
 )
 def test_to_dict(constructor_eager: ConstructorEager) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor_eager(data), eager_only=True)
     result = df.to_dict(as_series=False)
     assert result == data
 
 
 def test_to_dict_as_series(constructor_eager: ConstructorEager) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor_eager(data), eager_only=True)
     result = df.to_dict(as_series=True)
     assert isinstance(result["a"], nw.Series)
diff --git a/tests/frame/to_native_test.py b/tests/frame/to_native_test.py
index fb90caf1..08cf8efd 100644
--- a/tests/frame/to_native_test.py
+++ b/tests/frame/to_native_test.py
@@ -9,7 +9,7 @@ if TYPE_CHECKING:
 
 
 def test_to_native(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}
     df_raw = constructor(data)
     df = nw.from_native(df_raw)
 
diff --git a/tests/frame/to_numpy_test.py b/tests/frame/to_numpy_test.py
index e1179f3a..ca9d837e 100644
--- a/tests/frame/to_numpy_test.py
+++ b/tests/frame/to_numpy_test.py
@@ -16,11 +16,11 @@ if TYPE_CHECKING:
 
 
 def test_to_numpy(constructor_eager: ConstructorEager) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}
     df_raw = constructor_eager(data)
     result = nw.from_native(df_raw, eager_only=True).to_numpy()
 
-    expected = np.array([[1, 3, 2], [4, 4, 6], [7.1, 8, 9]]).T
+    expected = np.array([[1, 3, 2], [4, 4, 6], [7.1, 8.0, 9.0]]).T
     np.testing.assert_array_equal(result, expected)
     assert result.dtype == "float64"
 
diff --git a/tests/frame/to_pandas_test.py b/tests/frame/to_pandas_test.py
index 1bc588f3..07b35c58 100644
--- a/tests/frame/to_pandas_test.py
+++ b/tests/frame/to_pandas_test.py
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
 def test_convert_pandas(
     constructor_eager: ConstructorEager,
 ) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df_raw = constructor_eager(data)
     result = nw.from_native(df_raw).to_pandas()  # type: ignore[union-attr]
 
diff --git a/tests/frame/to_polars_test.py b/tests/frame/to_polars_test.py
index d8683cbd..cc2f860d 100644
--- a/tests/frame/to_polars_test.py
+++ b/tests/frame/to_polars_test.py
@@ -14,7 +14,7 @@ if TYPE_CHECKING:
 
 @pytest.mark.filterwarnings("ignore:.*Passing a BlockManager.*:DeprecationWarning")
 def test_convert_polars(constructor_eager: ConstructorEager) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}
     df_raw = constructor_eager(data)
     result = nw.from_native(df_raw).to_polars()  # type: ignore[union-attr]
 
diff --git a/tests/frame/unique_test.py b/tests/frame/unique_test.py
index a193ab98..8e1b71de 100644
--- a/tests/frame/unique_test.py
+++ b/tests/frame/unique_test.py
@@ -12,7 +12,7 @@ from narwhals.exceptions import ColumnNotFoundError
 from tests.utils import Constructor
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
 
 
 @pytest.mark.parametrize("subset", ["b", ["b"]])
diff --git a/tests/frame/with_columns_test.py b/tests/frame/with_columns_test.py
index 6fa3ab82..7badea6a 100644
--- a/tests/frame/with_columns_test.py
+++ b/tests/frame/with_columns_test.py
@@ -22,23 +22,23 @@ def test_with_columns_int_col_name_pandas() -> None:
 
 
 def test_with_columns_order(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.with_columns(nw.col("a") + 1, d=nw.col("a") - 1)
     assert result.collect_schema().names() == ["a", "b", "z", "d"]
-    expected = {"a": [2, 4, 3], "b": [4, 4, 6], "z": [7.0, 8, 9], "d": [0, 2, 1]}
+    expected = {"a": [2, 4, 3], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "d": [0, 2, 1]}
     assert_equal_data(result, expected)
 
 
 def test_with_columns_empty(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]}
     df = nw.from_native(constructor(data))
     result = df.select().with_columns()
     assert_equal_data(result, {})
 
 
 def test_with_columns_order_single_row(constructor: Constructor) -> None:
-    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8, 9], "i": [0, 1, 2]}
+    data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "i": [0, 1, 2]}
     df = nw.from_native(constructor(data)).filter(nw.col("i") < 1).drop("i")
     result = df.with_columns(nw.col("a") + 1, d=nw.col("a") - 1)
     assert result.collect_schema().names() == ["a", "b", "z", "d"]
diff --git a/tests/group_by_test.py b/tests/group_by_test.py
index 07ab9574..586b75dc 100644
--- a/tests/group_by_test.py
+++ b/tests/group_by_test.py
@@ -15,7 +15,7 @@ from tests.utils import Constructor
 from tests.utils import ConstructorEager
 from tests.utils import assert_equal_data
 
-data = {"a": [1, 1, 3], "b": [4, 4, 6], "c": [7.0, 8, 9]}
+data = {"a": [1, 1, 3], "b": [4, 4, 6], "c": [7.0, 8.0, 9.0]}
 
 df_pandas = pd.DataFrame(data)
 df_lazy = pl.LazyFrame(data)
diff --git a/tests/series_only/is_sorted_test.py b/tests/series_only/is_sorted_test.py
index 2ff6e50f..7fa02949 100644
--- a/tests/series_only/is_sorted_test.py
+++ b/tests/series_only/is_sorted_test.py
@@ -8,7 +8,7 @@ from tests.utils import assert_equal_data
 
 data = [1, 3, 2]
 data_dups = [4, 4, 6]
-data_sorted = [7.0, 8, 9]
+data_sorted = [7.0, 8.0, 9.0]
 
 
 @pytest.mark.parametrize(