Repository: great-expectations/great_expectations

Issue:
Miss configured AssetConfigSchema
**Describe the bug**
To instantiate a Data Source theres the possibility via [`context.test_yaml_config(yaml_config)`](https://github.com/great-expectations/great_expectations/blob/f867baf041a4c06517b3cd843bd3624205aad6af/great_expectations/data_context/data_context.py#L3384)

This function leads to a [schema check ](https://github.com/great-expectations/great_expectations/blob/f867baf041a4c06517b3cd843bd3624205aad6af/great_expectations/data_context/data_context.py#L1936).
If you wanna use a [ConfiguredAssetSqlDataConnector](https://github.com/great-expectations/great_expectations/blob/ebce61654d4bc1882d9f6db5b13ace07142977b3/great_expectations/datasource/data_connector/configured_asset_sql_data_connector.py#L27) you need to configure Assets. 
The config of these assets is used to [config sampling_method ](https://github.com/great-expectations/great_expectations/blob/ebce61654d4bc1882d9f6db5b13ace07142977b3/great_expectations/datasource/data_connector/configured_asset_sql_data_connector.py#L110) for example. 

Unfortunately the [schema of Assets](https://github.com/great-expectations/great_expectations/blob/f867baf041a4c06517b3cd843bd3624205aad6af/great_expectations/data_context/types/base.py#L181) as well as the [class](https://github.com/great-expectations/great_expectations/blob/74b51e78baccc66d55cf844a9c00991a0dd5267b/great_expectations/datasource/data_connector/asset/asset.py#L7) are not ment to store any config related to splitting. 
So in the Schema Check the fields related to splitting get removed.
https://github.com/great-expectations/great_expectations/blob/f867baf041a4c06517b3cd843bd3624205aad6af/great_expectations/data_context/data_context.py#L1936

Also it looks like the  ConfiguredAssetSqlDataConnector dont even store the Data Asses As Asset Class Objects. 
https://github.com/great-expectations/great_expectations/blob/ebce61654d4bc1882d9f6db5b13ace07142977b3/great_expectations/datasource/data_connector/configured_asset_sql_data_connector.py#L48-L50

**To Reproduce**
Sample yaml as input:
```
name: {datasource_name}
class_name: Datasource
execution_engine:
  class_name: SqlAlchemyExecutionEngine
  connection_string: {connection_string}
data_connectors:
  asset_based_connections:
    class_name: ConfiguredAssetSqlDataConnector
    assets:
        dummy_asset:
            table_name: baluuu
            schema_name: foo
            splitter_method: _split_on_column_value
            splitter_kwargs:
                column_name: pickup_datetime 
```

but lead to this configuration in the `great_expectations.yml`

```
datasources:
  asset_based_datasource:
    module_name: great_expectations.datasource
    data_connectors:
      asset_based_connections:
        module_name: great_expectations.datasource.data_connector
        class_name: ConfiguredAssetSqlDataConnector
        assets:
          dummy_asset:
            class_name: Asset
            module_name: great_expectations.datasource.data_connector.asset
            schema_name: foo
            table_name: baluuu
    class_name: Datasource
    execution_engine:
      class_name: SqlAlchemyExecutionEngine
      module_name: great_expectations.execution_engine
      connection_string: bigquery://project/temporary
```


**Expected behaviour**
The ConfiguredAssetSqlDataConnector need to be instantiate correct and store correct. 

**Environment (please complete the following information):**
 - Great Expectations Version: [0.14.9]

**Additional context**
Add any other context about the problem here.



Discussion:
Hey @MajorDaxx ! Thank you for surfacing this; we'll review internally and be in touch.

Resolving patch:
diff --git a/great_expectations/data_context/data_context/data_context.py b/great_expectations/data_context/data_context/data_context.py
--- a/great_expectations/data_context/data_context/data_context.py
+++ b/great_expectations/data_context/data_context/data_context.py
@@ -439,7 +439,7 @@ def _save_project_config(self):
         """Save the current project to disk."""
         if self.ge_cloud_mode:
             logger.debug(
-                "ge_cloud_mode detected - skipping DataContect._save_project_config"
+                "ge_cloud_mode detected - skipping DataContext._save_project_config"
             )
             return
         logger.debug("Starting DataContext._save_project_config")
diff --git a/great_expectations/data_context/types/base.py b/great_expectations/data_context/types/base.py
--- a/great_expectations/data_context/types/base.py
+++ b/great_expectations/data_context/types/base.py
@@ -124,7 +124,7 @@ def to_yaml_str(self) -> str:
 
     def to_json_dict(self) -> dict:
         """
-        :returns a JSON-serialiable dict containing the project configuration
+        :returns a JSON-serializable dict containing the project configuration
         """
         commented_map: CommentedMap = self.commented_map
         return convert_to_json_serializable(data=commented_map)
@@ -145,16 +145,18 @@ def get_schema_class(cls) -> None:
 class AssetConfig(DictDot):
     def __init__(
         self,
-        name=None,
-        class_name=None,
-        module_name=None,
-        bucket=None,
-        prefix=None,
-        delimiter=None,
-        max_keys=None,
-        schema_name=None,
-        batch_spec_passthrough=None,
-        batch_identifiers=None,
+        name: Optional[str] = None,
+        class_name: Optional[str] = None,
+        module_name: Optional[str] = None,
+        bucket: Optional[str] = None,
+        prefix: Optional[str] = None,
+        delimiter: Optional[str] = None,
+        max_keys: Optional[int] = None,
+        schema_name: Optional[str] = None,
+        batch_spec_passthrough: Optional[Dict[str, Any]] = None,
+        batch_identifiers: Optional[List[str]] = None,
+        splitter_method: Optional[str] = None,
+        splitter_kwargs: Optional[Dict[str, str]] = None,
         **kwargs,
     ) -> None:
         if name is not None:
@@ -175,6 +177,10 @@ def __init__(
             self.batch_spec_passthrough = batch_spec_passthrough
         if batch_identifiers is not None:
             self.batch_identifiers = batch_identifiers
+        if splitter_method is not None:
+            self.splitter_method = splitter_method
+        if splitter_kwargs is not None:
+            self.splitter_kwargs = splitter_kwargs
         for k, v in kwargs.items():
             setattr(self, k, v)
 
@@ -223,6 +229,9 @@ class Meta:
         cls_or_instance=fields.Str(), required=False, allow_none=True
     )
 
+    splitter_method = fields.String(required=False, allow_none=True)
+    splitter_kwargs = fields.Dict(required=False, allow_none=True)
+
     @validates_schema
     def validate_schema(self, data, **kwargs) -> None:
         pass
@@ -404,6 +413,7 @@ def __init__(
         if delimiter is not None:
             self.delimiter = delimiter
 
+        # Note: optional samplers and splitters are handled by setattr
         for k, v in kwargs.items():
             setattr(self, k, v)
 


Test patch:
diff --git a/tests/datasource/test_new_datasource_with_sql_data_connector.py b/tests/datasource/test_new_datasource_with_sql_data_connector.py
--- a/tests/datasource/test_new_datasource_with_sql_data_connector.py
+++ b/tests/datasource/test_new_datasource_with_sql_data_connector.py
@@ -2,10 +2,18 @@
 import logging
 import os
 import random
+from typing import Optional, Union
 
 import pytest
 from ruamel.yaml import YAML
 
+from great_expectations.datasource import (
+    BaseDatasource,
+    Datasource,
+    LegacyDatasource,
+    SimpleSqlalchemyDatasource,
+)
+
 logger = logging.getLogger(__name__)
 
 try:
@@ -99,14 +107,14 @@ def data_context_with_sql_data_connectors_including_schema_for_testing_get_batch
     return context
 
 
-def test_basic_instantiation_with_ConfiguredAssetSqlDataConnector(sa):
+def test_basic_instantiation_with_ConfiguredAssetSqlDataConnector_splitting(sa):
     random.seed(0)
 
     db_file = file_relative_path(
         __file__,
         os.path.join("..", "test_sets", "test_cases_for_sql_data_connector.db"),
     )
-    # This is a basic integration test demonstrating an Datasource containing a SQL data_connector
+    # This is a basic integration test demonstrating a Datasource containing a SQL data_connector
     # It also shows how to instantiate a SQLite SqlAlchemyExecutionEngine
     config = yaml.load(
         f"""
@@ -182,10 +190,77 @@ def test_basic_instantiation_with_ConfiguredAssetSqlDataConnector(sa):
     }
 
 
-def test_basic_instantiation_with_InferredAssetSqlDataConnector(sa):
+def test_instantiation_with_ConfiguredAssetSqlDataConnector_round_trip_to_config_splitting(
+    sa, empty_data_context
+):
+    # This is a basic integration test demonstrating a Datasource containing a SQL data_connector.
+    # It tests that splitter configurations can be saved and loaded to great_expectations.yml by performing a
+    # round-trip to the configuration.
+    context: DataContext = empty_data_context
+    db_file: Union[bytes, str] = file_relative_path(
+        __file__,
+        os.path.join("..", "test_sets", "test_cases_for_sql_data_connector.db"),
+    )
+    config: str = f"""
+    name: my_datasource
+    class_name: Datasource
+
+    execution_engine:
+        class_name: SqlAlchemyExecutionEngine
+        connection_string: sqlite:///{db_file}
+
+    data_connectors:
+        my_sqlite_db:
+            class_name: ConfiguredAssetSqlDataConnector
+
+            assets:
+                table_partitioned_by_date_column__A:
+                    splitter_method: _split_on_converted_datetime
+                    splitter_kwargs:
+                        column_name: date
+                        date_format_string: "%Y-%W"
+    """
+    context.add_datasource(**yaml.load(config))
+    datasource: Union[LegacyDatasource, BaseDatasource, None] = context.get_datasource(
+        datasource_name="my_datasource"
+    )
+    report: dict = datasource.self_check()
+    report["execution_engine"].pop("connection_string")
+    assert report == {
+        "execution_engine": {
+            "module_name": "great_expectations.execution_engine.sqlalchemy_execution_engine",
+            "class_name": "SqlAlchemyExecutionEngine",
+        },
+        "data_connectors": {
+            "count": 1,
+            "my_sqlite_db": {
+                "class_name": "ConfiguredAssetSqlDataConnector",
+                "data_asset_count": 1,
+                "example_data_asset_names": ["table_partitioned_by_date_column__A"],
+                "data_assets": {
+                    "table_partitioned_by_date_column__A": {
+                        "batch_definition_count": 5,
+                        "example_data_references": [
+                            {"date": "2020-00"},
+                            {"date": "2020-01"},
+                            {"date": "2020-02"},
+                        ],
+                    }
+                },
+                "unmatched_data_reference_count": 0,
+                "example_unmatched_data_references": [],
+            },
+        },
+    }
+
+
+def test_basic_instantiation_with_InferredAssetSqlDataConnector_splitting(sa):
+    # This is a basic integration test demonstrating a Datasource containing a SQL data_connector.
+    # It tests that splitter configurations can be saved and loaded to great_expectations.yml by performing a
+    # round-trip to the configuration.
     random.seed(0)
 
-    db_file = file_relative_path(
+    db_file: Union[bytes, str] = file_relative_path(
         __file__,
         os.path.join("..", "test_sets", "test_cases_for_sql_data_connector.db"),
     )
@@ -206,6 +281,10 @@ def test_basic_instantiation_with_InferredAssetSqlDataConnector(sa):
         name: whole_table
         data_asset_name_prefix: prefix__
         data_asset_name_suffix: __xiffus
+        splitter_method: _split_on_converted_datetime
+        splitter_kwargs:
+            column_name: date
+            date_format_string: "%Y-%W"
     """,
     )
 
@@ -215,11 +294,94 @@ def test_basic_instantiation_with_InferredAssetSqlDataConnector(sa):
         runtime_environment={"name": "my_sql_datasource"},
     )
     report = my_data_source.self_check()
+    report["execution_engine"].pop("connection_string")
+
+    assert report == {
+        "execution_engine": {
+            "module_name": "great_expectations.execution_engine.sqlalchemy_execution_engine",
+            "class_name": "SqlAlchemyExecutionEngine",
+        },
+        "data_connectors": {
+            "count": 1,
+            "my_sqlite_db": {
+                "class_name": "InferredAssetSqlDataConnector",
+                "data_asset_count": 6,
+                "example_data_asset_names": [
+                    "prefix__table_containing_id_spacers_for_D__xiffus",
+                    "prefix__table_full__I__xiffus",
+                    "prefix__table_partitioned_by_date_column__A__xiffus",
+                ],
+                "data_assets": {
+                    "prefix__table_containing_id_spacers_for_D__xiffus": {
+                        "batch_definition_count": 5,
+                        "example_data_references": [
+                            {"date": "2020-00"},
+                            {"date": "2020-01"},
+                            {"date": "2020-02"},
+                        ],
+                    },
+                    "prefix__table_full__I__xiffus": {
+                        "batch_definition_count": 5,
+                        "example_data_references": [
+                            {"date": "2020-00"},
+                            {"date": "2020-01"},
+                            {"date": "2020-02"},
+                        ],
+                    },
+                    "prefix__table_partitioned_by_date_column__A__xiffus": {
+                        "batch_definition_count": 5,
+                        "example_data_references": [
+                            {"date": "2020-00"},
+                            {"date": "2020-01"},
+                            {"date": "2020-02"},
+                        ],
+                    },
+                },
+                "unmatched_data_reference_count": 0,
+                "example_unmatched_data_references": [],
+            },
+        },
+    }
+
 
-    connection_string_to_test = f"""sqlite:///{db_file}"""
+def test_instantiation_with_InferredAssetSqlDataConnector_round_trip_to_config_splitting(
+    sa, empty_data_context
+):
+    # This is a basic integration test demonstrating a Datasource containing a SQL data_connector.
+    # It tests that splitter configurations can be saved and loaded to great_expectations.yml by performing a
+    # round-trip to the configuration.
+    context: DataContext = empty_data_context
+    db_file: Union[bytes, str] = file_relative_path(
+        __file__,
+        os.path.join("..", "test_sets", "test_cases_for_sql_data_connector.db"),
+    )
+    config: str = f"""
+    name: my_datasource
+    class_name: Datasource
+
+    execution_engine:
+        class_name: SqlAlchemyExecutionEngine
+        connection_string: sqlite:///{db_file}
+
+    data_connectors:
+        my_sqlite_db:
+            class_name: InferredAssetSqlDataConnector
+            name: whole_table
+            data_asset_name_prefix: prefix__
+            data_asset_name_suffix: __xiffus
+            splitter_method: _split_on_converted_datetime
+            splitter_kwargs:
+                column_name: date
+                date_format_string: "%Y-%W"
+        """
+    context.add_datasource(**yaml.load(config))
+    datasource: Union[LegacyDatasource, BaseDatasource, None] = context.get_datasource(
+        datasource_name="my_datasource"
+    )
+    report: dict = datasource.self_check()
+    report["execution_engine"].pop("connection_string")
     assert report == {
         "execution_engine": {
-            "connection_string": connection_string_to_test,
             "module_name": "great_expectations.execution_engine.sqlalchemy_execution_engine",
             "class_name": "SqlAlchemyExecutionEngine",
         },
@@ -227,7 +389,7 @@ def test_basic_instantiation_with_InferredAssetSqlDataConnector(sa):
             "count": 1,
             "my_sqlite_db": {
                 "class_name": "InferredAssetSqlDataConnector",
-                "data_asset_count": 21,
+                "data_asset_count": 6,
                 "example_data_asset_names": [
                     "prefix__table_containing_id_spacers_for_D__xiffus",
                     "prefix__table_full__I__xiffus",
@@ -235,16 +397,28 @@ def test_basic_instantiation_with_InferredAssetSqlDataConnector(sa):
                 ],
                 "data_assets": {
                     "prefix__table_containing_id_spacers_for_D__xiffus": {
-                        "batch_definition_count": 1,
-                        "example_data_references": [{}],
+                        "batch_definition_count": 5,
+                        "example_data_references": [
+                            {"date": "2020-00"},
+                            {"date": "2020-01"},
+                            {"date": "2020-02"},
+                        ],
                     },
                     "prefix__table_full__I__xiffus": {
-                        "batch_definition_count": 1,
-                        "example_data_references": [{}],
+                        "batch_definition_count": 5,
+                        "example_data_references": [
+                            {"date": "2020-00"},
+                            {"date": "2020-01"},
+                            {"date": "2020-02"},
+                        ],
                     },
                     "prefix__table_partitioned_by_date_column__A__xiffus": {
-                        "batch_definition_count": 1,
-                        "example_data_references": [{}],
+                        "batch_definition_count": 5,
+                        "example_data_references": [
+                            {"date": "2020-00"},
+                            {"date": "2020-01"},
+                            {"date": "2020-02"},
+                        ],
                     },
                 },
                 "unmatched_data_reference_count": 0,
diff --git a/tests/integration/db/test_sql_data_splitting.py b/tests/integration/db/test_sql_data_splitting.py
--- a/tests/integration/db/test_sql_data_splitting.py
+++ b/tests/integration/db/test_sql_data_splitting.py
@@ -9,6 +9,7 @@
 from great_expectations.core.batch import BatchDefinition, BatchRequest
 from great_expectations.core.batch_spec import SqlAlchemyDatasourceBatchSpec
 from great_expectations.core.yaml_handler import YAMLHandler
+from great_expectations.datasource import BaseDatasource, Datasource
 from great_expectations.datasource.data_connector import ConfiguredAssetSqlDataConnector
 from great_expectations.execution_engine.sqlalchemy_batch_data import (
     SqlAlchemyBatchData,
@@ -105,10 +106,24 @@ def _load_data(
         print("Testing splitter method:", test_case.splitter_method_name)
 
         # 1. Setup
-
         context: DataContext = ge.get_context()
 
         datasource_name: str = "test_datasource"
+        data_connector_name: str = "test_data_connector"
+        data_asset_name: str = table_name  # Read from generated table name
+        column_name: str = taxi_splitting_test_cases.test_column_name
+
+        # 2. Set splitter in DataConnector config
+        data_connector_config: dict = {
+            "class_name": "ConfiguredAssetSqlDataConnector",
+            "assets": {
+                data_asset_name: {
+                    "splitter_method": test_case.splitter_method_name,
+                    "splitter_kwargs": test_case.splitter_kwargs,
+                }
+            },
+        }
+
         context.add_datasource(
             name=datasource_name,
             class_name="Datasource",
@@ -116,26 +131,17 @@ def _load_data(
                 "class_name": "SqlAlchemyExecutionEngine",
                 "connection_string": connection_string,
             },
+            data_connectors={data_connector_name: data_connector_config},
         )
 
-        # 2. Set splitter in data connector config
-        data_connector_name: str = "test_data_connector"
-        data_asset_name: str = table_name  # Read from generated table name
-        column_name: str = taxi_splitting_test_cases.test_column_name
-        data_connector: ConfiguredAssetSqlDataConnector = (
-            ConfiguredAssetSqlDataConnector(
-                name=data_connector_name,
-                datasource_name=datasource_name,
-                execution_engine=context.datasources[datasource_name].execution_engine,
-                assets={
-                    data_asset_name: {
-                        "splitter_method": test_case.splitter_method_name,
-                        "splitter_kwargs": test_case.splitter_kwargs,
-                    }
-                },
-            )
+        datasource: BaseDatasource = context.get_datasource(
+            datasource_name="test_datasource"
         )
 
+        data_connector: ConfiguredAssetSqlDataConnector = datasource.data_connectors[
+            "test_data_connector"
+        ]
+
         # 3. Check if resulting batches are as expected
         # using data_connector.get_batch_definition_list_from_batch_request()
         batch_request: BatchRequest = BatchRequest(
diff --git a/tests/integration/fixtures/split_and_sample_data/splitter_test_cases_and_fixtures.py b/tests/integration/fixtures/split_and_sample_data/splitter_test_cases_and_fixtures.py
--- a/tests/integration/fixtures/split_and_sample_data/splitter_test_cases_and_fixtures.py
+++ b/tests/integration/fixtures/split_and_sample_data/splitter_test_cases_and_fixtures.py
@@ -126,7 +126,7 @@ def test_cases(self) -> List[TaxiSplittingTestCase]:
                 splitter_method_name="split_on_date_parts",
                 splitter_kwargs={
                     "column_name": self.taxi_test_data.test_column_name,
-                    "date_parts": [DatePart.MONTH],
+                    "date_parts": [DatePart.MONTH.name],
                 },
                 num_expected_batch_definitions=12,
                 num_expected_rows_in_first_batch_definition=30,
@@ -137,7 +137,7 @@ def test_cases(self) -> List[TaxiSplittingTestCase]:
                 splitter_method_name="split_on_date_parts",
                 splitter_kwargs={
                     "column_name": self.taxi_test_data.test_column_name,
-                    "date_parts": [DatePart.YEAR, "mOnTh"],
+                    "date_parts": [DatePart.YEAR.name, "mOnTh"],
                 },
                 num_expected_batch_definitions=36,
                 num_expected_rows_in_first_batch_definition=10,