Repository: great-expectations/great_expectations

Issue:
Use cleaner solution for non-truncating division in python 2
Prefer `from __future__ import division` to `1.*x/y`


Discussion:
Done inline during improve_partitions push.

Resolving patch:
diff --git a/great_expectations/dataset/sqlalchemy_dataset.py b/great_expectations/dataset/sqlalchemy_dataset.py
--- a/great_expectations/dataset/sqlalchemy_dataset.py
+++ b/great_expectations/dataset/sqlalchemy_dataset.py
@@ -784,36 +784,42 @@ def get_column_unique_count(self, column):
         )
 
     def get_column_median(self, column):
-        # AWS Athena does not support offset
+        # AWS Athena and presto have an special function that can be used to retrieve the median
         if self.sql_engine_dialect.name.lower() == "awsathena":
-            raise NotImplementedError("AWS Athena does not support OFFSET.")
-        nonnull_count = self.get_column_nonnull_count(column)
-        element_values = self.engine.execute(
-            sa.select([sa.column(column)])
-            .order_by(sa.column(column))
-            .where(sa.column(column) != None)
-            .offset(max(nonnull_count // 2 - 1, 0))
-            .limit(2)
-            .select_from(self._table)
-        )
+            element_values = self.engine.execute(
+                f"SELECT approx_percentile({column},  0.5) FROM {self._table}"
+            )
+            return convert_to_json_serializable(element_values.fetchone()[0])
+        else:
 
-        column_values = list(element_values.fetchall())
+            nonnull_count = self.get_column_nonnull_count(column)
+            element_values = self.engine.execute(
+                sa.select([sa.column(column)])
+                .order_by(sa.column(column))
+                .where(sa.column(column) != None)
+                .offset(max(nonnull_count // 2 - 1, 0))
+                .limit(2)
+                .select_from(self._table)
+            )
 
-        if len(column_values) == 0:
-            column_median = None
-        elif nonnull_count % 2 == 0:
-            # An even number of column values: take the average of the two center values
-            column_median = (
-                float(
-                    column_values[0][0]
-                    + column_values[1][0]  # left center value  # right center value
-                )
-                / 2.0
-            )  # Average center values
-        else:
-            # An odd number of column values, we can just take the center value
-            column_median = column_values[1][0]  # True center value
-        return convert_to_json_serializable(column_median)
+            column_values = list(element_values.fetchall())
+
+            if len(column_values) == 0:
+                column_median = None
+            elif nonnull_count % 2 == 0:
+                # An even number of column values: take the average of the two center values
+                column_median = (
+                    float(
+                        column_values[0][0]
+                        + column_values[1][0]  # left center value  # right center value
+                    )
+                    / 2.0
+                )  # Average center values
+            else:
+                # An odd number of column values, we can just take the center value
+                column_median = column_values[1][0]  # True center value
+
+            return convert_to_json_serializable(column_median)
 
     def get_column_quantiles(
         self, column: str, quantiles: Iterable, allow_relative_error: bool = False
@@ -1242,11 +1248,20 @@ def create_temporary_table(self, table_name, custom_sql, schema_name=None):
         # similar, for example.
         ###
 
-        if self.sql_engine_dialect.name.lower() == "bigquery":
+        engine_dialect = self.sql_engine_dialect.name.lower()
+        # handle cases where dialect.name.lower() returns a byte string (e.g. databricks)
+        if isinstance(engine_dialect, bytes):
+            engine_dialect = str(engine_dialect, "utf-8")
+
+        if engine_dialect == "bigquery":
             stmt = "CREATE OR REPLACE VIEW `{table_name}` AS {custom_sql}".format(
                 table_name=table_name, custom_sql=custom_sql
             )
-        elif self.sql_engine_dialect.name.lower() == "snowflake":
+        elif engine_dialect == "databricks":
+            stmt = "CREATE OR REPLACE VIEW `{table_name}` AS {custom_sql}".format(
+                table_name=table_name, custom_sql=custom_sql
+            )
+        elif engine_dialect == "snowflake":
             table_type = "TEMPORARY" if self.generated_table_name else "TRANSIENT"
 
             logger.info("Creating temporary table %s" % table_name)
@@ -1272,7 +1287,7 @@ def create_temporary_table(self, table_name, custom_sql, schema_name=None):
             stmt = (
                 custom_sqlmod[0] + "into {table_name} from" + custom_sqlmod[1]
             ).format(table_name=table_name)
-        elif self.sql_engine_dialect.name.lower() == "awsathena":
+        elif engine_dialect == "awsathena":
             stmt = "CREATE TABLE {table_name} AS {custom_sql}".format(
                 table_name=table_name, custom_sql=custom_sql
             )
diff --git a/great_expectations/expectations/metrics/column_aggregate_metrics/column_proportion_of_unique_values.py b/great_expectations/expectations/metrics/column_aggregate_metrics/column_proportion_of_unique_values.py
--- a/great_expectations/expectations/metrics/column_aggregate_metrics/column_proportion_of_unique_values.py
+++ b/great_expectations/expectations/metrics/column_aggregate_metrics/column_proportion_of_unique_values.py
@@ -20,11 +20,13 @@
 
 
 def unique_proportion(_metrics):
+    """Computes the proportion of unique non-null values out of all non-null values"""
     total_values = _metrics.get("table.row_count")
     unique_values = _metrics.get("column.distinct_values.count")
     null_count = _metrics.get("column_values.nonnull.unexpected_count")
 
-    if total_values > 0:
+    # Ensuring that we do not divide by 0, returning 0 if all values are nulls (we only consider non-nulls unique values)
+    if total_values > 0 and total_values != null_count:
         return unique_values / (total_values - null_count)
     else:
         return 0
diff --git a/great_expectations/render/renderer/suite_scaffold_notebook_renderer.py b/great_expectations/render/renderer/suite_scaffold_notebook_renderer.py
--- a/great_expectations/render/renderer/suite_scaffold_notebook_renderer.py
+++ b/great_expectations/render/renderer/suite_scaffold_notebook_renderer.py
@@ -18,45 +18,41 @@ def __init__(self, context: DataContext, suite: ExpectationSuite, batch_kwargs):
 
     def add_header(self):
         self.add_markdown_cell(
-            """# Scaffold a new Expectation Suite (Experimental)
-This process helps you avoid writing lots of boilerplate when authoring suites by allowing you to select columns you care about and letting a profiler write some candidate expectations for you to adjust.
+            f"""# Scaffold a new Expectation Suite (Experimental)
+This process helps you avoid writing lots of boilerplate when authoring suites by allowing you to select columns and other factors that you care about and letting a profiler write some candidate expectations for you to adjust.
 
-**Expectation Suite Name**: `{}`
+**Expectation Suite Name**: `{self.suite_name}`
 
-We'd love it if you'd **reach out to us on** the [**Great Expectations Slack Channel**](https://greatexpectations.io/slack)!""".format(
-                self.suite_name
-            )
+We'd love it if you'd **reach out to us on** the [**Great Expectations Slack Channel**](https://greatexpectations.io/slack)!"""
         )
 
         if not self.batch_kwargs:
             self.batch_kwargs = dict()
         self.add_code_cell(
-            """\
-import datetime
+            f"""\
 import great_expectations as ge
-import great_expectations.jupyter_ux
 from great_expectations.checkpoint import LegacyCheckpoint
-from great_expectations.profile import BasicSuiteBuilderProfiler
+from great_expectations.profile.user_configurable_profiler import UserConfigurableProfiler
 from great_expectations.data_context.types.resource_identifiers import ValidationResultIdentifier
 
 context = ge.data_context.DataContext()
 
-expectation_suite_name = "{}"
+expectation_suite_name = "{self.suite_name}"
+
+# Wipe the suite clean to prevent unwanted expectations in the batch
 suite = context.create_expectation_suite(expectation_suite_name, overwrite_existing=True)
 
-batch_kwargs = {}
+batch_kwargs = {self.batch_kwargs}
 batch = context.get_batch(batch_kwargs, suite)
-batch.head()""".format(
-                self.suite_name, self.batch_kwargs
-            ),
+batch.head()""",
             lint=True,
         )
 
     def _add_scaffold_column_list(self):
-        columns = [f"    # '{col}'" for col in self.batch.get_table_columns()]
+        columns = [f"    '{col}'" for col in self.batch.get_table_columns()]
         columns = ",\n".join(columns)
         code = f"""\
-included_columns = [
+ignored_columns = [
 {columns}
 ]"""
         self.add_code_cell(code, lint=True)
@@ -125,11 +121,11 @@ def render(self, batch_kwargs=None, **kwargs) -> nbformat.NotebookNode:
         self._notebook = nbformat.v4.new_notebook()
         self.add_header()
         self.add_markdown_cell(
-            """## Select the columns on which you would like to scaffold expectations
+            """## Select the columns on which you would like to scaffold expectations and those which you would like to ignore.
 
 Great Expectations will choose which expectations might make sense for a column based on the **data type** and **cardinality** of the data in each selected column.
 
-Simply uncomment columns that are important. You can select multiple lines and
+Simply comment out columns that are important and should be included. You can select multiple lines and
 use a jupyter keyboard shortcut to toggle each line: **Linux/Windows**:
 `Ctrl-/`, **macOS**: `Cmd-/`"""
         )
@@ -144,10 +140,11 @@ def render(self, batch_kwargs=None, **kwargs) -> nbformat.NotebookNode:
 suite](https://docs.greatexpectations.io/en/latest/guides/how_to_guides/creating_and_editing_expectations/how_to_edit_an_expectation_suite_using_a_disposable_notebook.html?utm_source=notebook&utm_medium=scaffold_expectations)
 after scaffolding gets you close to what you want.**
 
-This is highly configurable depending on your goals. You can include or exclude
-columns, and include or exclude expectation types (when applicable). [The
-Expectation Glossary](https://docs.greatexpectations.io/en/latest/reference/glossary_of_expectations.html?utm_source=notebook&utm_medium=scaffold_expectations)
-contains a list of possible expectations."""
+This is highly configurable depending on your goals.
+You can ignore columns or exclude certain expectations, specify a threshold for creating value set expectations, or even specify semantic types for a given column.
+You can find more information about [how to configure this profiler, including a list of the expectations that it uses, here.](https://docs.greatexpectations.io/en/latest/guides/how_to_guides/creating_and_editing_expectations/how_to_create_an_expectation_suite_with_the_user_configurable_profiler.html)
+
+"""
         )
         self._add_scaffold_cell()
         self.add_footer()
@@ -165,17 +162,16 @@ def render_to_disk(self, notebook_file_path: str) -> None:
 
     def _add_scaffold_cell(self):
         self.add_code_cell(
-            """\
-# Wipe the suite clean to prevent unwanted expectations in the batch
-suite = context.create_expectation_suite(expectation_suite_name, overwrite_existing=True)
-batch = context.get_batch(batch_kwargs, suite)
-
-# In the scaffold_config, included or excluded expectation names should be strings.
-scaffold_config = {
-    "included_columns": included_columns,
-    # "excluded_columns": [],
-    # "included_expectations": [],
-    # "excluded_expectations": [],
-}
-suite, evr = BasicSuiteBuilderProfiler().profile(batch, profiler_configuration=scaffold_config)"""
+            f"""\
+profiler = UserConfigurableProfiler(profile_dataset=batch,
+    ignored_columns=ignored_columns,
+    excluded_expectations=None,
+    not_null_only=False,
+    primary_or_compound_key=False,
+    semantic_types_dict=None,
+    table_expectations_only=False,
+    value_set_threshold="MANY",
+    )
+
+suite = profiler.build_suite()"""
         )


Test patch:
diff --git a/tests/profile/test_user_configurable_profiler_v2_batch_kwargs.py b/tests/profile/test_user_configurable_profiler_v2_batch_kwargs.py
--- a/tests/profile/test_user_configurable_profiler_v2_batch_kwargs.py
+++ b/tests/profile/test_user_configurable_profiler_v2_batch_kwargs.py
@@ -11,6 +11,7 @@
 from great_expectations.profile.user_configurable_profiler import (
     UserConfigurableProfiler,
 )
+from tests.profile.conftest import get_set_of_columns_and_expectations_from_suite
 
 
 @pytest.fixture()
@@ -61,22 +62,6 @@ def possible_expectations_set():
     }
 
 
-def get_set_of_columns_and_expectations_from_suite(suite):
-    """
-    Args:
-        suite: An expectation suite
-
-    Returns:
-        A tuple containing a set of columns and a set of expectations found in a suite
-    """
-    columns = {
-        i.kwargs.get("column") for i in suite.expectations if i.kwargs.get("column")
-    }
-    expectations = {i.expectation_type for i in suite.expectations}
-
-    return columns, expectations
-
-
 def test_profiler_init_no_config(
     cardinality_dataset,
 ):
diff --git a/tests/render/renderer/test_suite_scaffold_notebook_renderer.py b/tests/render/renderer/test_suite_scaffold_notebook_renderer.py
--- a/tests/render/renderer/test_suite_scaffold_notebook_renderer.py
+++ b/tests/render/renderer/test_suite_scaffold_notebook_renderer.py
@@ -7,118 +7,7 @@
 from great_expectations.render.renderer.suite_scaffold_notebook_renderer import (
     SuiteScaffoldNotebookRenderer,
 )
-
-
-def test_render_snapshot_test(titanic_data_context_stats_enabled_no_config_store):
-    batch_kwargs = (
-        titanic_data_context_stats_enabled_no_config_store.build_batch_kwargs(
-            "mydatasource", "mygenerator", "Titanic"
-        )
-    )
-    csv_path = batch_kwargs["path"]
-    suite_name = "my_suite"
-    suite = titanic_data_context_stats_enabled_no_config_store.create_expectation_suite(
-        suite_name
-    )
-    renderer = SuiteScaffoldNotebookRenderer(
-        titanic_data_context_stats_enabled_no_config_store, suite, batch_kwargs
-    )
-    obs = renderer.render(None)
-    assert isinstance(obs, nbformat.NotebookNode)
-    ## NOTE!!! - When updating this snapshot be sure to include the dynamic
-    # csv_path in the second cell due to pytest fixtures
-    expected = {
-        "nbformat": 4,
-        "nbformat_minor": 4,
-        "metadata": {},
-        "cells": [
-            {
-                "cell_type": "markdown",
-                "source": """# Scaffold a new Expectation Suite (Experimental)
-This process helps you avoid writing lots of boilerplate when authoring suites by allowing you to select columns you care about and letting a profiler write some candidate expectations for you to adjust.
-
-**Expectation Suite Name**: `my_suite`
-
-We'd love it if you'd **reach out to us on** the [**Great Expectations Slack Channel**](https://greatexpectations.io/slack)!""",
-                "metadata": {},
-            },
-            {
-                "cell_type": "code",
-                "metadata": {},
-                "execution_count": None,
-                "source": 'import datetime\nimport great_expectations as ge\nimport great_expectations.jupyter_ux\nfrom great_expectations.checkpoint import LegacyCheckpoint\nfrom great_expectations.profile import BasicSuiteBuilderProfiler\nfrom great_expectations.data_context.types.resource_identifiers import (\n    ValidationResultIdentifier,\n)\n\ncontext = ge.data_context.DataContext()\n\nexpectation_suite_name = "my_suite"\nsuite = context.create_expectation_suite(\n    expectation_suite_name, overwrite_existing=True\n)\n\nbatch_kwargs = {\n    "path": "'
-                + csv_path
-                + '",\n    "datasource": "mydatasource",\n    "data_asset_name": "Titanic",\n}\nbatch = context.get_batch(batch_kwargs, suite)\nbatch.head()',
-                "outputs": [],
-            },
-            {
-                "cell_type": "markdown",
-                "source": """## Select the columns on which you would like to scaffold expectations
-
-Great Expectations will choose which expectations might make sense for a column based on the **data type** and **cardinality** of the data in each selected column.
-
-Simply uncomment columns that are important. You can select multiple lines and
-use a jupyter keyboard shortcut to toggle each line: **Linux/Windows**:
-`Ctrl-/`, **macOS**: `Cmd-/`""",
-                "metadata": {},
-            },
-            {
-                "cell_type": "code",
-                "metadata": {},
-                "execution_count": None,
-                "source": "included_columns = [\n    # 'Unnamed: 0',\n    # 'Name',\n    # 'PClass',\n    # 'Age',\n    # 'Sex',\n    # 'Survived',\n    # 'SexCode'\n]",
-                "outputs": [],
-            },
-            {
-                "cell_type": "markdown",
-                "source": """## Run the scaffolder
-
-The suites generated here are **not meant to be production suites** - they are **scaffolds to build upon**.
-
-**To get to a production grade suite, you will definitely want to [edit this
-suite](https://docs.greatexpectations.io/en/latest/guides/how_to_guides/creating_and_editing_expectations/how_to_edit_an_expectation_suite_using_a_disposable_notebook.html?utm_source=notebook&utm_medium=scaffold_expectations)
-after scaffolding gets you close to what you want.**
-
-This is highly configurable depending on your goals. You can include or exclude
-columns, and include or exclude expectation types (when applicable). [The
-Expectation Glossary](https://docs.greatexpectations.io/en/latest/reference/glossary_of_expectations.html?utm_source=notebook&utm_medium=scaffold_expectations)
-contains a list of possible expectations.""",
-                "metadata": {},
-            },
-            {
-                "cell_type": "code",
-                "metadata": {},
-                "execution_count": None,
-                "source": '# Wipe the suite clean to prevent unwanted expectations in the batch\nsuite = context.create_expectation_suite(expectation_suite_name, overwrite_existing=True)\nbatch = context.get_batch(batch_kwargs, suite)\n\n# In the scaffold_config, included or excluded expectation names should be strings.\nscaffold_config = {\n    "included_columns": included_columns,\n    # "excluded_columns": [],\n    # "included_expectations": [],\n    # "excluded_expectations": [],\n}\nsuite, evr = BasicSuiteBuilderProfiler().profile(batch, profiler_configuration=scaffold_config)',
-                "outputs": [],
-            },
-            {
-                "cell_type": "markdown",
-                "source": "## Save & review the scaffolded Expectation Suite\n\nLet's save the scaffolded expectation suite as a JSON file in the\n`great_expectations/expectations` directory of your project and rebuild the Data\n Docs site to make it easy to review the scaffolded suite.",
-                "metadata": {},
-            },
-            {
-                "cell_type": "code",
-                "metadata": {},
-                "execution_count": None,
-                "source": "context.save_expectation_suite(suite, expectation_suite_name)\n\nresults = "
-                'LegacyCheckpoint(\n    name="_temp_checkpoint",\n    data_context=context,\n    batches=[\n        {\n          "batch_kwargs": batch_kwargs,\n          "expectation_suite_names": [expectation_suite_name]\n        }\n    ],\n    validation_operator_name="action_list_operator"\n).run()\nvalidation_result_identifier = results.list_validation_result_identifiers()[0]\ncontext.build_data_docs()\ncontext.open_data_docs(validation_result_identifier)',
-                "outputs": [],
-            },
-            {
-                "cell_type": "markdown",
-                "source": "## Next steps\nAfter you review this scaffolded Expectation Suite in Data Docs you\nshould edit this suite to make finer grained adjustments to the expectations.\nThis can be done by running `great_expectations suite edit my_suite`.",
-                "metadata": {},
-            },
-        ],
-    }
-    del expected["nbformat_minor"]
-    del obs["nbformat_minor"]
-
-    for obs_cell, expected_cell in zip(obs["cells"], expected["cells"]):
-        obs_cell.pop("id", None)
-        assert obs_cell == expected_cell
-    assert obs == expected
+from tests.profile.conftest import get_set_of_columns_and_expectations_from_suite
 
 
 def test_notebook_execution_with_pandas_backend(titanic_data_context_no_data_docs):
@@ -193,10 +82,22 @@ def test_notebook_execution_with_pandas_backend(titanic_data_context_no_data_doc
     context = DataContext(root_dir)
     obs_validation_result = context.get_validation_result(suite_name)
     assert obs_validation_result.statistics == {
-        "evaluated_expectations": 3,
-        "successful_expectations": 3,
+        "evaluated_expectations": 2,
+        "successful_expectations": 2,
         "unsuccessful_expectations": 0,
         "success_percent": 100,
     }
     suite = context.get_expectation_suite(suite_name)
+
     assert suite.expectations
+    (
+        columns_with_expectations,
+        expectations_from_suite,
+    ) = get_set_of_columns_and_expectations_from_suite(suite)
+
+    expected_expectations = {
+        "expect_table_columns_to_match_ordered_list",
+        "expect_table_row_count_to_be_between",
+    }
+    assert columns_with_expectations == set()
+    assert expectations_from_suite == expected_expectations
diff --git a/tests/render/renderer/test_suite_scaffold_notebook_renderer_pre_v013.py b/tests/render/renderer/test_suite_scaffold_notebook_renderer_pre_v013.py
--- a/tests/render/renderer/test_suite_scaffold_notebook_renderer_pre_v013.py
+++ b/tests/render/renderer/test_suite_scaffold_notebook_renderer_pre_v013.py
@@ -7,112 +7,7 @@
 from great_expectations.render.renderer.suite_scaffold_notebook_renderer import (
     SuiteScaffoldNotebookRenderer,
 )
-
-
-def test_render_snapshot_test(titanic_data_context):
-    batch_kwargs = titanic_data_context.build_batch_kwargs(
-        "mydatasource", "mygenerator", "Titanic"
-    )
-    csv_path = batch_kwargs["path"]
-    suite_name = "my_suite"
-    suite = titanic_data_context.create_expectation_suite(suite_name)
-    renderer = SuiteScaffoldNotebookRenderer(titanic_data_context, suite, batch_kwargs)
-    obs = renderer.render(None)
-    assert isinstance(obs, nbformat.NotebookNode)
-    ## NOTE!!! - When updating this snapshot be sure to include the dynamic
-    # csv_path in the second cell due to pytest fixtures
-    expected = {
-        "nbformat": 4,
-        "nbformat_minor": 4,
-        "metadata": {},
-        "cells": [
-            {
-                "cell_type": "markdown",
-                "source": """# Scaffold a new Expectation Suite (Experimental)
-This process helps you avoid writing lots of boilerplate when authoring suites by allowing you to select columns you care about and letting a profiler write some candidate expectations for you to adjust.
-
-**Expectation Suite Name**: `my_suite`
-
-We'd love it if you'd **reach out to us on** the [**Great Expectations Slack Channel**](https://greatexpectations.io/slack)!""",
-                "metadata": {},
-            },
-            {
-                "cell_type": "code",
-                "metadata": {},
-                "execution_count": None,
-                "source": 'import datetime\nimport great_expectations as ge\nimport great_expectations.jupyter_ux\nfrom great_expectations.checkpoint import LegacyCheckpoint\nfrom great_expectations.profile import BasicSuiteBuilderProfiler\nfrom great_expectations.data_context.types.resource_identifiers import (\n    ValidationResultIdentifier,\n)\n\ncontext = ge.data_context.DataContext()\n\nexpectation_suite_name = "my_suite"\nsuite = context.create_expectation_suite(\n    expectation_suite_name, overwrite_existing=True\n)\n\nbatch_kwargs = {\n    "path": "'
-                + csv_path
-                + '",\n    "datasource": "mydatasource",\n    "data_asset_name": "Titanic",\n}\nbatch = context.get_batch(batch_kwargs, suite)\nbatch.head()',
-                "outputs": [],
-            },
-            {
-                "cell_type": "markdown",
-                "source": """## Select the columns on which you would like to scaffold expectations
-
-Great Expectations will choose which expectations might make sense for a column based on the **data type** and **cardinality** of the data in each selected column.
-
-Simply uncomment columns that are important. You can select multiple lines and
-use a jupyter keyboard shortcut to toggle each line: **Linux/Windows**:
-`Ctrl-/`, **macOS**: `Cmd-/`""",
-                "metadata": {},
-            },
-            {
-                "cell_type": "code",
-                "metadata": {},
-                "execution_count": None,
-                "source": "included_columns = [\n    # 'Unnamed: 0',\n    # 'Name',\n    # 'PClass',\n    # 'Age',\n    # 'Sex',\n    # 'Survived',\n    # 'SexCode'\n]",
-                "outputs": [],
-            },
-            {
-                "cell_type": "markdown",
-                "source": """## Run the scaffolder
-
-The suites generated here are **not meant to be production suites** - they are **scaffolds to build upon**.
-
-**To get to a production grade suite, you will definitely want to [edit this
-suite](https://docs.greatexpectations.io/en/latest/guides/how_to_guides/creating_and_editing_expectations/how_to_edit_an_expectation_suite_using_a_disposable_notebook.html?utm_source=notebook&utm_medium=scaffold_expectations)
-after scaffolding gets you close to what you want.**
-
-This is highly configurable depending on your goals. You can include or exclude
-columns, and include or exclude expectation types (when applicable). [The
-Expectation Glossary](https://docs.greatexpectations.io/en/latest/reference/glossary_of_expectations.html?utm_source=notebook&utm_medium=scaffold_expectations)
-contains a list of possible expectations.""",
-                "metadata": {},
-            },
-            {
-                "cell_type": "code",
-                "metadata": {},
-                "execution_count": None,
-                "source": '# Wipe the suite clean to prevent unwanted expectations in the batch\nsuite = context.create_expectation_suite(expectation_suite_name, overwrite_existing=True)\nbatch = context.get_batch(batch_kwargs, suite)\n\n# In the scaffold_config, included or excluded expectation names should be strings.\nscaffold_config = {\n    "included_columns": included_columns,\n    # "excluded_columns": [],\n    # "included_expectations": [],\n    # "excluded_expectations": [],\n}\nsuite, evr = BasicSuiteBuilderProfiler().profile(batch, profiler_configuration=scaffold_config)',
-                "outputs": [],
-            },
-            {
-                "cell_type": "markdown",
-                "source": "## Save & review the scaffolded Expectation Suite\n\nLet's save the scaffolded expectation suite as a JSON file in the\n`great_expectations/expectations` directory of your project and rebuild the Data\n Docs site to make it easy to review the scaffolded suite.",
-                "metadata": {},
-            },
-            {
-                "cell_type": "code",
-                "metadata": {},
-                "execution_count": None,
-                "source": "context.save_expectation_suite(suite, expectation_suite_name)\n\nresults = "
-                'LegacyCheckpoint(\n    name="_temp_checkpoint",\n    data_context=context,\n    batches=[\n        {\n          "batch_kwargs": batch_kwargs,\n          "expectation_suite_names": [expectation_suite_name]\n        }\n    ],\n    validation_operator_name="action_list_operator"\n).run()\nvalidation_result_identifier = results.list_validation_result_identifiers()[0]\ncontext.build_data_docs()\ncontext.open_data_docs(validation_result_identifier)',
-                "outputs": [],
-            },
-            {
-                "cell_type": "markdown",
-                "source": "## Next steps\nAfter you review this scaffolded Expectation Suite in Data Docs you\nshould edit this suite to make finer grained adjustments to the expectations.\nThis can be done by running `great_expectations suite edit my_suite`.",
-                "metadata": {},
-            },
-        ],
-    }
-    del expected["nbformat_minor"]
-    del obs["nbformat_minor"]
-
-    for obs_cell, expected_cell in zip(obs["cells"], expected["cells"]):
-        obs_cell.pop("id", None)
-        assert obs_cell == expected_cell
-    assert obs == expected
+from tests.profile.conftest import get_set_of_columns_and_expectations_from_suite
 
 
 def test_notebook_execution_with_pandas_backend(
@@ -189,10 +84,22 @@ def test_notebook_execution_with_pandas_backend(
     context = DataContext(root_dir)
     obs_validation_result = context.get_validation_result(suite_name)
     assert obs_validation_result.statistics == {
-        "evaluated_expectations": 3,
-        "successful_expectations": 3,
+        "evaluated_expectations": 2,
+        "successful_expectations": 2,
         "unsuccessful_expectations": 0,
         "success_percent": 100,
     }
     suite = context.get_expectation_suite(suite_name)
+
     assert suite.expectations
+    (
+        columns_with_expectations,
+        expectations_from_suite,
+    ) = get_set_of_columns_and_expectations_from_suite(suite)
+
+    expected_expectations = {
+        "expect_table_columns_to_match_ordered_list",
+        "expect_table_row_count_to_be_between",
+    }
+    assert columns_with_expectations == set()
+    assert expectations_from_suite == expected_expectations