Repository: great-expectations/great_expectations
Pull request #11108: [FEATURE] Add `ColumnDescriptiveStats` metric
Author: login: NathanFarmer
Created: 2025-04-17T15:31:19Z | Merged: 2025-04-17T20:44:14Z



- [x] Description of PR changes above includes a link to [an existing GitHub issue](https://github.com/great-expectations/great_expectations/issues)
- [x] PR title is prefixed with one of: [BUGFIX], [FEATURE], [DOCS], [MAINTENANCE], [CONTRIB], [MINORBUMP]
- [x] Code is linted - run `invoke lint` (uses `ruff format` + `ruff check`)
- [x] Appropriate tests and docs have been updated




Diff:
diff --git a/great_expectations/expectations/metrics/column_aggregate_metrics/column_descriptive_stats.py b/great_expectations/expectations/metrics/column_aggregate_metrics/column_descriptive_stats.py
new file mode 100644
index 000000000000..6b522f03540e
--- /dev/null
+++ b/great_expectations/expectations/metrics/column_aggregate_metrics/column_descriptive_stats.py
@@ -0,0 +1,109 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Optional
+
+from great_expectations.compatibility.pydantic import BaseModel
+from great_expectations.compatibility.typing_extensions import override
+from great_expectations.execution_engine import (
+    ExecutionEngine,
+    PandasExecutionEngine,
+    SparkDFExecutionEngine,
+    SqlAlchemyExecutionEngine,
+)
+from great_expectations.expectations.metrics.column_aggregate_metric_provider import (
+    ColumnAggregateMetricProvider,
+)
+from great_expectations.expectations.metrics.metric_provider import metric_value
+from great_expectations.validator.metric_configuration import MetricConfiguration
+
+if TYPE_CHECKING:
+    from great_expectations.expectations.expectation_configuration import (
+        ExpectationConfiguration,
+    )
+
+
+class DescriptiveStats(BaseModel):
+    min: float
+    max: float
+    mean: float
+    standard_deviation: float
+
+
+class ColumnDescriptiveStats(ColumnAggregateMetricProvider):
+    metric_name = "column.descriptive_stats"
+
+    @metric_value(engine=PandasExecutionEngine)
+    def _pandas(
+        cls,
+        metrics: dict[str, int],
+        **kwargs,
+    ) -> DescriptiveStats:
+        return DescriptiveStats(
+            min=metrics["column.min"],
+            max=metrics["column.max"],
+            mean=metrics["column.mean"],
+            standard_deviation=metrics["column.standard_deviation"],
+        )
+
+    @metric_value(engine=SqlAlchemyExecutionEngine)
+    def _sqlalchemy(
+        cls,
+        metrics: dict[str, int],
+        **kwargs,
+    ) -> DescriptiveStats:
+        return DescriptiveStats(
+            min=metrics["column.min"],
+            max=metrics["column.max"],
+            mean=metrics["column.mean"],
+            standard_deviation=metrics["column.standard_deviation"],
+        )
+
+    @metric_value(engine=SparkDFExecutionEngine)
+    def _spark(
+        cls,
+        metrics: dict[str, int],
+        **kwargs,
+    ) -> DescriptiveStats:
+        return DescriptiveStats(
+            min=metrics["column.min"],
+            max=metrics["column.max"],
+            mean=metrics["column.mean"],
+            standard_deviation=metrics["column.standard_deviation"],
+        )
+
+    @classmethod
+    @override
+    def _get_evaluation_dependencies(
+        cls,
+        metric: MetricConfiguration,
+        configuration: Optional[ExpectationConfiguration] = None,
+        execution_engine: Optional[ExecutionEngine] = None,
+        runtime_configuration: Optional[dict] = None,
+    ):
+        dependencies: dict = super()._get_evaluation_dependencies(
+            metric=metric,
+            configuration=configuration,
+            execution_engine=execution_engine,
+            runtime_configuration=runtime_configuration,
+        )
+        dependencies["column.min"] = MetricConfiguration(
+            metric_name="column.min",
+            metric_domain_kwargs=metric.metric_domain_kwargs,
+            metric_value_kwargs=None,
+        )
+        dependencies["column.max"] = MetricConfiguration(
+            metric_name="column.max",
+            metric_domain_kwargs=metric.metric_domain_kwargs,
+            metric_value_kwargs=None,
+        )
+        dependencies["column.mean"] = MetricConfiguration(
+            metric_name="column.mean",
+            metric_domain_kwargs=metric.metric_domain_kwargs,
+            metric_value_kwargs=None,
+        )
+        dependencies["column.standard_deviation"] = MetricConfiguration(
+            metric_name="column.standard_deviation",
+            metric_domain_kwargs=metric.metric_domain_kwargs,
+            metric_value_kwargs=None,
+        )
+        return dependencies
diff --git a/great_expectations/metrics/column/column_descriptive_stats.py b/great_expectations/metrics/column/column_descriptive_stats.py
new file mode 100644
index 000000000000..e4007f6f4dd4
--- /dev/null
+++ b/great_expectations/metrics/column/column_descriptive_stats.py
@@ -0,0 +1,12 @@
+from great_expectations.expectations.metrics.column_aggregate_metrics.column_descriptive_stats import (  # noqa: E501
+    DescriptiveStats,
+)
+from great_expectations.metrics.column import ColumnMetric
+from great_expectations.metrics.metric_results import MetricResult
+
+
+class ColumnDescriptiveStatsResult(MetricResult[DescriptiveStats]): ...
+
+
+class ColumnDescriptiveStats(ColumnMetric[ColumnDescriptiveStatsResult]):
+    name = "column.descriptive_stats"
diff --git a/tests/integration/metrics/column/test_column_descriptive_stats.py b/tests/integration/metrics/column/test_column_descriptive_stats.py
new file mode 100644
index 000000000000..5f8caa93a6be
--- /dev/null
+++ b/tests/integration/metrics/column/test_column_descriptive_stats.py
@@ -0,0 +1,36 @@
+import math
+
+import pandas as pd
+
+from great_expectations.datasource.fluent.interfaces import Batch
+from great_expectations.metrics.column.column_descriptive_stats import (
+    ColumnDescriptiveStats,
+    ColumnDescriptiveStatsResult,
+)
+from tests.integration.conftest import parameterize_batch_for_data_sources
+from tests.metrics.conftest import ALL_DATA_SOURCES
+
+COLUMN_NAME = "whatevs"
+DATA_FRAME = pd.DataFrame(
+    {
+        COLUMN_NAME: [1, 1, 2, 2, 3, 3, 4, 4, 5, 5],
+    },
+)
+
+
+class TestColumnDescriptiveStats:
+    @parameterize_batch_for_data_sources(
+        data_source_configs=ALL_DATA_SOURCES,
+        data=DATA_FRAME,
+    )
+    def test_descriptive_stats(self, batch_for_datasource: Batch) -> None:
+        metric = ColumnDescriptiveStats(column=COLUMN_NAME)
+        metric_result = batch_for_datasource.compute_metrics(metric)
+
+        assert isinstance(metric_result, ColumnDescriptiveStatsResult)
+        assert metric_result.value.min == 1
+        assert metric_result.value.max == 5
+        assert metric_result.value.mean == 3
+        assert math.isclose(
+            metric_result.value.standard_deviation, 1.4907119849998598, rel_tol=1e-6, abs_tol=0.0
+        )


Reviews:
user: login: tyler-hoffman
body: Question about the data type, but it looks good!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T17:13:01Z
user: login: NathanFarmer
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T17:34:25Z
user: login: NathanFarmer
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T17:38:48Z
user: login: tyler-hoffman
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T17:41:09Z

Review comments:
diff_hunk: @@ -0,0 +1,108 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, NamedTuple, Optional
+
+from great_expectations.compatibility.typing_extensions import override
+from great_expectations.execution_engine import (
+    ExecutionEngine,
+    PandasExecutionEngine,
+    SparkDFExecutionEngine,
+    SqlAlchemyExecutionEngine,
+)
+from great_expectations.expectations.metrics.column_aggregate_metric_provider import (
+    ColumnAggregateMetricProvider,
+)
+from great_expectations.expectations.metrics.metric_provider import metric_value
+from great_expectations.validator.metric_configuration import MetricConfiguration
+
+if TYPE_CHECKING:
+    from great_expectations.expectations.expectation_configuration import (
+        ExpectationConfiguration,
+    )
+
+
+class DescriptiveStats(NamedTuple):
path: great_expectations/expectations/metrics/column_aggregate_metrics/column_descriptive_stats.py
user: login: tyler-hoffman
body: Not a blocker, but why a named tuple? I guess I would have expected a dataclass, since using this as a tuple seems like an easy way to mix up which value is which.
created_at: 2025-04-17T17:10:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,108 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, NamedTuple, Optional
+
+from great_expectations.compatibility.typing_extensions import override
+from great_expectations.execution_engine import (
+    ExecutionEngine,
+    PandasExecutionEngine,
+    SparkDFExecutionEngine,
+    SqlAlchemyExecutionEngine,
+)
+from great_expectations.expectations.metrics.column_aggregate_metric_provider import (
+    ColumnAggregateMetricProvider,
+)
+from great_expectations.expectations.metrics.metric_provider import metric_value
+from great_expectations.validator.metric_configuration import MetricConfiguration
+
+if TYPE_CHECKING:
+    from great_expectations.expectations.expectation_configuration import (
+        ExpectationConfiguration,
+    )
+
+
+class DescriptiveStats(NamedTuple):
path: great_expectations/expectations/metrics/column_aggregate_metrics/column_descriptive_stats.py
user: login: NathanFarmer
body: I guess at first I was just going to return 4 values, which by default is a tuple, and then I named those values. I actually see now that the consumer uses a `BaseModel` so I think I'll just do that. It should functionally work the same regardless though...
created_at: 2025-04-17T17:34:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,108 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, NamedTuple, Optional
+
+from great_expectations.compatibility.typing_extensions import override
+from great_expectations.execution_engine import (
+    ExecutionEngine,
+    PandasExecutionEngine,
+    SparkDFExecutionEngine,
+    SqlAlchemyExecutionEngine,
+)
+from great_expectations.expectations.metrics.column_aggregate_metric_provider import (
+    ColumnAggregateMetricProvider,
+)
+from great_expectations.expectations.metrics.metric_provider import metric_value
+from great_expectations.validator.metric_configuration import MetricConfiguration
+
+if TYPE_CHECKING:
+    from great_expectations.expectations.expectation_configuration import (
+        ExpectationConfiguration,
+    )
+
+
+class DescriptiveStats(NamedTuple):
path: great_expectations/expectations/metrics/column_aggregate_metrics/column_descriptive_stats.py
user: login: NathanFarmer
body: > since using this as a tuple seems like an easy way to mix up which value is which

Why doesn't adding the names solve that problem? I guess because you can still use indexing?
created_at: 2025-04-17T17:38:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,108 @@
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, NamedTuple, Optional
+
+from great_expectations.compatibility.typing_extensions import override
+from great_expectations.execution_engine import (
+    ExecutionEngine,
+    PandasExecutionEngine,
+    SparkDFExecutionEngine,
+    SqlAlchemyExecutionEngine,
+)
+from great_expectations.expectations.metrics.column_aggregate_metric_provider import (
+    ColumnAggregateMetricProvider,
+)
+from great_expectations.expectations.metrics.metric_provider import metric_value
+from great_expectations.validator.metric_configuration import MetricConfiguration
+
+if TYPE_CHECKING:
+    from great_expectations.expectations.expectation_configuration import (
+        ExpectationConfiguration,
+    )
+
+
+class DescriptiveStats(NamedTuple):
path: great_expectations/expectations/metrics/column_aggregate_metrics/column_descriptive_stats.py
user: login: tyler-hoffman
body: Yeah, I just feel like if it's used as a tuple, 4 values of the same type makes it a bit easier to e.g. confuse mean with standard dev.
created_at: 2025-04-17T17:41:09Z
author_association: CONTRIBUTOR

PR comments:
user: login: netlify[bot]
created_at: 2025-04-17T15:31:37Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *niobium-lead-7998* canceled.


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 02110b84c3da6d163cffa9642d4ce527b36f730e |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/niobium-lead-7998/deploys/68013c7738a5eb0008f8e5ad |
author_association: NONE
user: login: codecov[bot]
created_at: 2025-04-17T15:34:16Z
body: ## [Codecov](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 81.16%. Comparing base [(`cf19349`)](https://app.codecov.io/gh/great-expectations/great_expectations/commit/cf193495fdb21a56130d06f59e75c5d8948f2a37?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) to head [(`02110b8`)](https://app.codecov.io/gh/great-expectations/great_expectations/commit/02110b84c3da6d163cffa9642d4ce527b36f730e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations).
> Report is 2 commits behind head on develop.

:white_check_mark: All tests successful. No failed tests found.

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff             @@
##           develop   #11108      +/-   ##
===========================================
+ Coverage    81.15%   81.16%   +0.01%     
===========================================
  Files          500      502       +2     
  Lines        41385    41424      +39     
===========================================
+ Hits         33585    33621      +36     
- Misses        7800     7803       +3     
```

| [Flag](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | Coverage Δ | |
|---|---|---|
| [3.10](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `70.46% <94.87%> (+0.02%)` | :arrow_up: |
| [3.11](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `70.46% <94.87%> (+0.02%)` | :arrow_up: |
| [3.12](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `70.45% <94.87%> (+0.02%)` | :arrow_up: |
| [3.12 athena or openpyxl or pyarrow or project or sqlite or aws_creds](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `57.10% <94.87%> (+0.03%)` | :arrow_up: |
| [3.12 aws_deps](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `46.83% <76.92%> (+0.02%)` | :arrow_up: |
| [3.12 big](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `55.17% <76.92%> (+0.02%)` | :arrow_up: |
| [3.12 bigquery](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `49.58% <94.87%> (+0.04%)` | :arrow_up: |
| [3.12 databricks](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `51.20% <94.87%> (+0.04%)` | :arrow_up: |
| [3.12 filesystem](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `63.26% <94.87%> (+0.02%)` | :arrow_up: |
| [3.12 gx-redshift](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `48.76% <76.92%> (+0.02%)` | :arrow_up: |
| [3.12 mssql](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `52.08% <76.92%> (+0.02%)` | :arrow_up: |
| [3.12 mysql](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `52.33% <76.92%> (+0.02%)` | :arrow_up: |
| [3.12 postgresql](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `55.15% <94.87%> (+0.03%)` | :arrow_up: |
| [3.12 redshift](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `48.74% <76.92%> (+0.01%)` | :arrow_up: |
| [3.12 snowflake](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `51.97% <94.87%> (+0.04%)` | :arrow_up: |
| [3.12 spark](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `58.27% <94.87%> (+0.03%)` | :arrow_up: |
| [3.12 spark_connect](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `47.15% <76.92%> (+0.02%)` | :arrow_up: |
| [3.12 trino](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `52.75% <76.92%> (+0.02%)` | :arrow_up: |
| [3.9](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `70.48% <94.87%> (+0.02%)` | :arrow_up: |
| [3.9 athena or openpyxl or pyarrow or project or sqlite or aws_creds](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `57.10% <94.87%> (+0.03%)` | :arrow_up: |
| [3.9 aws_deps](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `46.85% <76.92%> (+0.02%)` | :arrow_up: |
| [3.9 big](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `55.18% <76.92%> (+0.02%)` | :arrow_up: |
| [3.9 bigquery](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `49.57% <94.87%> (+0.04%)` | :arrow_up: |
| [3.9 clickhouse](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `43.79% <76.92%> (+0.03%)` | :arrow_up: |
| [3.9 databricks](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `51.20% <94.87%> (+0.04%)` | :arrow_up: |
| [3.9 filesystem](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `63.27% <94.87%> (+0.02%)` | :arrow_up: |
| [3.9 gx-redshift](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `48.75% <76.92%> (+0.02%)` | :arrow_up: |
| [3.9 mssql](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `52.06% <76.92%> (+0.02%)` | :arrow_up: |
| [3.9 mysql](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `52.31% <76.92%> (+0.02%)` | :arrow_up: |
| [3.9 postgresql](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `55.13% <94.87%> (+0.03%)` | :arrow_up: |
| [3.9 redshift](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `48.77% <76.92%> (+0.05%)` | :arrow_up: |
| [3.9 snowflake](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `51.97% <94.87%> (+0.04%)` | :arrow_up: |
| [3.9 spark](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `58.23% <94.87%> (+0.03%)` | :arrow_up: |
| [3.9 spark_connect](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `47.16% <76.92%> (+0.02%)` | :arrow_up: |
| [3.9 trino](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `52.74% <76.92%> (+0.02%)` | :arrow_up: |
| [cloud](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `0.00% <0.00%> (ø)` | |
| [docs-basic](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `54.03% <0.00%> (-0.06%)` | :arrow_down: |
| [docs-creds-needed](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `52.90% <0.00%> (-0.05%)` | :arrow_down: |
| [docs-spark](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations) | `52.47% <0.00%> (-0.05%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/great-expectations/great_expectations/pull/11108?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=great-expectations).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE