bigtesty 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. bigtesty-0.1.0/LICENSE +21 -0
  2. bigtesty-0.1.0/PKG-INFO +220 -0
  3. bigtesty-0.1.0/README.md +202 -0
  4. bigtesty-0.1.0/bigtesty/__init__.py +0 -0
  5. bigtesty-0.1.0/bigtesty/arguments.py +7 -0
  6. bigtesty-0.1.0/bigtesty/cli/__init__.py +0 -0
  7. bigtesty-0.1.0/bigtesty/cli/cli_env_vars.py +13 -0
  8. bigtesty-0.1.0/bigtesty/cli/main.py +102 -0
  9. bigtesty-0.1.0/bigtesty/dataset_helper.py +4 -0
  10. bigtesty-0.1.0/bigtesty/definition_test_config_helper.py +57 -0
  11. bigtesty-0.1.0/bigtesty/definition_test_file_exception.py +2 -0
  12. bigtesty-0.1.0/bigtesty/files_loader_helper.py +12 -0
  13. bigtesty-0.1.0/bigtesty/given/__init__.py +0 -0
  14. bigtesty-0.1.0/bigtesty/given/insertion_test_data_bigquery.py +43 -0
  15. bigtesty-0.1.0/bigtesty/infra/__init__.py +0 -0
  16. bigtesty-0.1.0/bigtesty/infra/create_iac_for_datasets_with_tables.py +50 -0
  17. bigtesty-0.1.0/bigtesty/infra/datasets_with_tables_config_file_loader.py +28 -0
  18. bigtesty-0.1.0/bigtesty/infra/datasets_with_tables_factory.py +55 -0
  19. bigtesty-0.1.0/bigtesty/infra/launch_tests_ephemeral_infra.py +134 -0
  20. bigtesty-0.1.0/bigtesty/lambda_functions.py +1 -0
  21. bigtesty-0.1.0/bigtesty/then/__init__.py +0 -0
  22. bigtesty-0.1.0/bigtesty/then/assertion_and_tests_reports_result.py +227 -0
  23. bigtesty-0.1.0/bigtesty/then/assertion_types.py +6 -0
  24. bigtesty-0.1.0/bigtesty/then/failure_test_exception.py +2 -0
  25. bigtesty-0.1.0/bigtesty.egg-info/PKG-INFO +220 -0
  26. bigtesty-0.1.0/bigtesty.egg-info/SOURCES.txt +30 -0
  27. bigtesty-0.1.0/bigtesty.egg-info/dependency_links.txt +1 -0
  28. bigtesty-0.1.0/bigtesty.egg-info/entry_points.txt +4 -0
  29. bigtesty-0.1.0/bigtesty.egg-info/requires.txt +6 -0
  30. bigtesty-0.1.0/bigtesty.egg-info/top_level.txt +1 -0
  31. bigtesty-0.1.0/setup.cfg +4 -0
  32. bigtesty-0.1.0/setup.py +42 -0
bigtesty-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Mazlum Tosun
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.1
2
+ Name: bigtesty
3
+ Version: 0.1.0
4
+ Summary: BigTesty is an integration testing framework for BigQuery
5
+ Home-page: https://github.com/tosun-si/bigtesty
6
+ Author: Mazlum TOSUN
7
+ Author-email: mazlum.tosun@gmail.com
8
+ License: UNKNOWN
9
+ Platform: UNKNOWN
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.9.19
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+
17
+ # BigTesty
18
+
19
+ BigTesty is a framework that allows to create Integration Tests with BigQuery on a real and short-lived Infrastructure.
20
+
21
+ Integration and End-to-End tests are a robust way to validate if SQL queries work as expected.\
22
+ There is no an emulator in this case and the queries are executed directly in the BigQuery Engine.
23
+
24
+ BigTesty isolates the tests for each execution to prevent collisions.\
25
+ Multiples developers or CI CD pipelines can execute tests at the same time.
26
+
27
+ The infrastructure proposed for the tests is ephemeral by default, but we can keep it if needed, to analyse the\
28
+ result in BigQuery.
29
+
30
+ After each test, a report result is returned to indicate the good and failure cases.
31
+
32
+ ![bigtesty_pulumi_automation.png](diagram%2Fbigtesty_pulumi_automation.png)
33
+
34
+ ## Getting started
35
+
36
+ There is a `Python` package for BigTesty and it can be installed from `PiPy`:
37
+
38
+ ```bash
39
+ pip install bigtesty
40
+ ```
41
+
42
+ ## How to run tests
43
+
44
+ **You need to be authenticated with Google Cloud Platform before running command.**
45
+
46
+ We recommend to be authenticated with [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials)
47
+
48
+ ```bash
49
+ gcloud auth application-default login
50
+ ```
51
+
52
+ ### Example of code structure
53
+
54
+ ![bigtesty_examples_code_structure.png](bigtesty-doc%2Fstatic%2Fimg%2Fbigtesty_examples_code_structure.png)
55
+
56
+ **The root test folder**
57
+
58
+ This folder contains all the testing definition files and the tests scenarios. The format is Json.
59
+
60
+ Example of a scenarios with a nominal case `definition_spec_failure_by_feature_name_no_error.json`:
61
+
62
+ ```json
63
+ {
64
+ "description": "Test of monitoring data",
65
+ "scenarios": [
66
+ {
67
+ "description": "Nominal case find failure by feature name",
68
+ "given": [
69
+ {
70
+ "input_file_path": "monitoring/given/input_failures_feature_name.json",
71
+ "destination_dataset": "monitoring",
72
+ "destination_table": "job_failure"
73
+ }
74
+ ],
75
+ "then": [
76
+ {
77
+ "fields_to_ignore": [
78
+ "\\[\\d+\\]\\['dwhCreationDate']"
79
+ ],
80
+ "actual_file_path": "monitoring/when/find_failures_by_feature_name.sql",
81
+ "expected_file_path": "monitoring/then/expected_failures_feature_name.json"
82
+ }
83
+ ]
84
+ }
85
+ ]
86
+ }
87
+ ```
88
+
89
+ In this example, there is only one scenario with 3 blocs:
90
+ - `given`: a list of input test data to ingest to the BigQuery tables. The input data can be proposed in a separate `Json` file or directly embedded. `input_file_path` for a separate file and `input` for an embedded object.
91
+ - `then`: a list of objects contains the SQL query to test and execute and the expected data. `actual/actual_file_path` => SQL query | `expected/expected_file_path` => expected data
92
+
93
+ **The root tables folder**
94
+
95
+ This folder contains the resources concerning the `BigQuery` `datasets` and `tables` to create.\
96
+ For example, all the `BigQuery` schemas are proposed in this folder.
97
+
98
+ **The tables config file**
99
+
100
+ The config file that lists all the `BigQuery` `datasets` and `tables` to create in a `Json` format.
101
+
102
+ Example:
103
+
104
+ ```json
105
+ [
106
+ {
107
+ "datasetId": "monitoring",
108
+ "datasetRegion": "EU",
109
+ "datasetFriendlyName": "Monitoring Dataset",
110
+ "datasetDescription": "Monitoring Dataset description",
111
+ "tables": [
112
+ {
113
+ "tableId": "job_failure",
114
+ "autodetect": false,
115
+ "tableSchemaPath": "schema/monitoring/job_failure.json",
116
+ "partitionType": "DAY",
117
+ "partitionField": "dwhCreationDate",
118
+ "clustering": [
119
+ "featureName",
120
+ "jobName",
121
+ "componentType"
122
+ ]
123
+ }
124
+ ]
125
+ }
126
+ ]
127
+ ```
128
+
129
+ In this example, we have a dataset called `monitoring` with the metadata.\
130
+ This dataset contains a table called `job_failure` with the metadata. Some fields can target on the `BigQuery` schemas proposed in the `root tables folder`.
131
+
132
+ ### Run with CLI
133
+
134
+ We need to pass the 3 parameters indicated in the previous section, in the command line to launch the tests:
135
+
136
+ - root-test-folder: the root folder containing all the testing files
137
+ - root-tables-folder: the root folder containing all the needed files to create the datasets and tables in BigQuery (Json schema...)
138
+ - tables-config-file: the Json configuration file that lists all the datasets and tables to create in BigQuery
139
+
140
+ Also, common GCP parameters like:
141
+ - project: the GCP project ID
142
+ - region: the GCP region
143
+
144
+ `BigTesty` uses an ephemeral infra internally via the concept of Infra As Code and the backend to host the state must be a `cloud Storage` bucket.\
145
+ We need to pass the backend URL via parameter in the CLI:
146
+ - iac-backend-url
147
+
148
+ The tests can be executed with the following command line:
149
+
150
+ ```bash
151
+ bigtesty test \
152
+ --project $PROJECT_ID \
153
+ --region $LOCATION \
154
+ --iac-backend-url gs://$IAC_BUCKET_STATE/bigtesty \
155
+ --root-test-folder $(pwd)/examples/tests \
156
+ --root-tables-folder $(pwd)/examples/tests/tables \
157
+ --tables-config-file $(pwd)/examples/tests/tables/tables.json
158
+ ```
159
+
160
+ **All the testing files showed in the documentation are accessible from the `examples` folder proposed at the root of the `BigTesty` repo.**
161
+
162
+ ### Run with Docker
163
+
164
+ Instead of pass the arguments by the CLI, we can also pass them with environment variables.
165
+
166
+ ```bash
167
+ export PROJECT_ID={{project_id}}
168
+ export LOCATION={{region}}
169
+ export IAC_BACKEND_URL=gs://{{gcs_state_bucket}}/bigtesty
170
+ export ROOT_TEST_FOLDER=/opt/bigtesty/tests
171
+ export ROOT_TABLES_FOLDER=/opt/bigtesty/tests/tables
172
+ export TABLES_CONFIG_FILE_PATH=/opt/bigtesty/tests/tables/tables.json
173
+
174
+ docker run -it \
175
+ -e GOOGLE_PROJECT=$PROJECT_ID \
176
+ -e GOOGLE_REGION=$LOCATION \
177
+ -e IAC_BACKEND_URL=$IAC_BACKEND_URL \
178
+ -e TABLES_CONFIG_FILE="$TABLES_CONFIG_FILE_PATH" \
179
+ -e ROOT_TEST_FOLDER=$ROOT_TEST_FOLDER \
180
+ -e ROOT_TABLES_FOLDER="$ROOT_TABLES_FOLDER" \
181
+ -v $(pwd)/examples/tests:/opt/bigtesty/tests \
182
+ -v $(pwd)/examples/tests/tables:/opt/bigtesty/tests/tables \
183
+ -v $HOME/.config/gcloud:/opt/bigtesty/.config/gcloud \
184
+ groupbees/bigtesty test
185
+ ```
186
+
187
+ Some explanations:
188
+
189
+ All the parameters are passed as environment variables.\
190
+ We need also to mount as volumes:
191
+ - the tests root folder : `-v $(pwd)/examples/tests:/opt/bigtesty/tests`
192
+ - the tables root folder: `-v $(pwd)/examples/tests/tables:/opt/bigtesty/tests/tables`
193
+ - the `gcloud` configuration: `-v $HOME/.config/gcloud:/opt/bigtesty/.config/gcloud`
194
+
195
+ When the authentication is done with Applications Default Credentials via the following command `gcloud auth application-default login`,\
196
+ a short-lived credential is generated in the local `gcloud` configuration: `$HOME/.config/gcloud`
197
+
198
+ To prevent the use of a long-lived SA token key, we can share and mount as volume the local `gcloud` configuration with the `Docker` container: `-v $HOME/.config/gcloud:/opt/bigtesty/.config/gcloud`\
199
+ With this technic, the container will be authenticated in Google Cloud securely, with your current user in the Shell session.
200
+
201
+ ### Run with Cloud Build
202
+
203
+ ```bash
204
+ export PROJECT_ID={{project_id}}
205
+ export LOCATION={{region}}
206
+ export IAC_BACKEND_URL=gs://{{gcs_state_bucket}}/bigtesty
207
+
208
+ gcloud builds submit \
209
+ --project=$PROJECT_ID \
210
+ --region=$LOCATION \
211
+ --config examples/ci/cloud_build/run-tests-cloud-build.yaml \
212
+ --substitutions _IAC_BACKEND_URL=$IAC_BACKEND_URL \
213
+ --verbosity="debug" .
214
+ ```
215
+
216
+ ## Contributing
217
+
218
+ cf. [CONTRIBUTING](CONTRIBUTING.md).
219
+
220
+
@@ -0,0 +1,202 @@
1
+ # BigTesty
2
+
3
+ BigTesty is a framework that allows to create Integration Tests with BigQuery on a real and short-lived Infrastructure.
4
+
5
+ Integration and End-to-End tests are a robust way to validate if SQL queries work as expected.\
6
+ There is no an emulator in this case and the queries are executed directly in the BigQuery Engine.
7
+
8
+ BigTesty isolates the tests for each execution to prevent collisions.\
9
+ Multiples developers or CI CD pipelines can execute tests at the same time.
10
+
11
+ The infrastructure proposed for the tests is ephemeral by default, but we can keep it if needed, to analyse the\
12
+ result in BigQuery.
13
+
14
+ After each test, a report result is returned to indicate the good and failure cases.
15
+
16
+ ![bigtesty_pulumi_automation.png](diagram%2Fbigtesty_pulumi_automation.png)
17
+
18
+ ## Getting started
19
+
20
+ There is a `Python` package for BigTesty and it can be installed from `PiPy`:
21
+
22
+ ```bash
23
+ pip install bigtesty
24
+ ```
25
+
26
+ ## How to run tests
27
+
28
+ **You need to be authenticated with Google Cloud Platform before running command.**
29
+
30
+ We recommend to be authenticated with [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials)
31
+
32
+ ```bash
33
+ gcloud auth application-default login
34
+ ```
35
+
36
+ ### Example of code structure
37
+
38
+ ![bigtesty_examples_code_structure.png](bigtesty-doc%2Fstatic%2Fimg%2Fbigtesty_examples_code_structure.png)
39
+
40
+ **The root test folder**
41
+
42
+ This folder contains all the testing definition files and the tests scenarios. The format is Json.
43
+
44
+ Example of a scenarios with a nominal case `definition_spec_failure_by_feature_name_no_error.json`:
45
+
46
+ ```json
47
+ {
48
+ "description": "Test of monitoring data",
49
+ "scenarios": [
50
+ {
51
+ "description": "Nominal case find failure by feature name",
52
+ "given": [
53
+ {
54
+ "input_file_path": "monitoring/given/input_failures_feature_name.json",
55
+ "destination_dataset": "monitoring",
56
+ "destination_table": "job_failure"
57
+ }
58
+ ],
59
+ "then": [
60
+ {
61
+ "fields_to_ignore": [
62
+ "\\[\\d+\\]\\['dwhCreationDate']"
63
+ ],
64
+ "actual_file_path": "monitoring/when/find_failures_by_feature_name.sql",
65
+ "expected_file_path": "monitoring/then/expected_failures_feature_name.json"
66
+ }
67
+ ]
68
+ }
69
+ ]
70
+ }
71
+ ```
72
+
73
+ In this example, there is only one scenario with 3 blocs:
74
+ - `given`: a list of input test data to ingest to the BigQuery tables. The input data can be proposed in a separate `Json` file or directly embedded. `input_file_path` for a separate file and `input` for an embedded object.
75
+ - `then`: a list of objects contains the SQL query to test and execute and the expected data. `actual/actual_file_path` => SQL query | `expected/expected_file_path` => expected data
76
+
77
+ **The root tables folder**
78
+
79
+ This folder contains the resources concerning the `BigQuery` `datasets` and `tables` to create.\
80
+ For example, all the `BigQuery` schemas are proposed in this folder.
81
+
82
+ **The tables config file**
83
+
84
+ The config file that lists all the `BigQuery` `datasets` and `tables` to create in a `Json` format.
85
+
86
+ Example:
87
+
88
+ ```json
89
+ [
90
+ {
91
+ "datasetId": "monitoring",
92
+ "datasetRegion": "EU",
93
+ "datasetFriendlyName": "Monitoring Dataset",
94
+ "datasetDescription": "Monitoring Dataset description",
95
+ "tables": [
96
+ {
97
+ "tableId": "job_failure",
98
+ "autodetect": false,
99
+ "tableSchemaPath": "schema/monitoring/job_failure.json",
100
+ "partitionType": "DAY",
101
+ "partitionField": "dwhCreationDate",
102
+ "clustering": [
103
+ "featureName",
104
+ "jobName",
105
+ "componentType"
106
+ ]
107
+ }
108
+ ]
109
+ }
110
+ ]
111
+ ```
112
+
113
+ In this example, we have a dataset called `monitoring` with the metadata.\
114
+ This dataset contains a table called `job_failure` with the metadata. Some fields can target on the `BigQuery` schemas proposed in the `root tables folder`.
115
+
116
+ ### Run with CLI
117
+
118
+ We need to pass the 3 parameters indicated in the previous section, in the command line to launch the tests:
119
+
120
+ - root-test-folder: the root folder containing all the testing files
121
+ - root-tables-folder: the root folder containing all the needed files to create the datasets and tables in BigQuery (Json schema...)
122
+ - tables-config-file: the Json configuration file that lists all the datasets and tables to create in BigQuery
123
+
124
+ Also, common GCP parameters like:
125
+ - project: the GCP project ID
126
+ - region: the GCP region
127
+
128
+ `BigTesty` uses an ephemeral infra internally via the concept of Infra As Code and the backend to host the state must be a `cloud Storage` bucket.\
129
+ We need to pass the backend URL via parameter in the CLI:
130
+ - iac-backend-url
131
+
132
+ The tests can be executed with the following command line:
133
+
134
+ ```bash
135
+ bigtesty test \
136
+ --project $PROJECT_ID \
137
+ --region $LOCATION \
138
+ --iac-backend-url gs://$IAC_BUCKET_STATE/bigtesty \
139
+ --root-test-folder $(pwd)/examples/tests \
140
+ --root-tables-folder $(pwd)/examples/tests/tables \
141
+ --tables-config-file $(pwd)/examples/tests/tables/tables.json
142
+ ```
143
+
144
+ **All the testing files showed in the documentation are accessible from the `examples` folder proposed at the root of the `BigTesty` repo.**
145
+
146
+ ### Run with Docker
147
+
148
+ Instead of pass the arguments by the CLI, we can also pass them with environment variables.
149
+
150
+ ```bash
151
+ export PROJECT_ID={{project_id}}
152
+ export LOCATION={{region}}
153
+ export IAC_BACKEND_URL=gs://{{gcs_state_bucket}}/bigtesty
154
+ export ROOT_TEST_FOLDER=/opt/bigtesty/tests
155
+ export ROOT_TABLES_FOLDER=/opt/bigtesty/tests/tables
156
+ export TABLES_CONFIG_FILE_PATH=/opt/bigtesty/tests/tables/tables.json
157
+
158
+ docker run -it \
159
+ -e GOOGLE_PROJECT=$PROJECT_ID \
160
+ -e GOOGLE_REGION=$LOCATION \
161
+ -e IAC_BACKEND_URL=$IAC_BACKEND_URL \
162
+ -e TABLES_CONFIG_FILE="$TABLES_CONFIG_FILE_PATH" \
163
+ -e ROOT_TEST_FOLDER=$ROOT_TEST_FOLDER \
164
+ -e ROOT_TABLES_FOLDER="$ROOT_TABLES_FOLDER" \
165
+ -v $(pwd)/examples/tests:/opt/bigtesty/tests \
166
+ -v $(pwd)/examples/tests/tables:/opt/bigtesty/tests/tables \
167
+ -v $HOME/.config/gcloud:/opt/bigtesty/.config/gcloud \
168
+ groupbees/bigtesty test
169
+ ```
170
+
171
+ Some explanations:
172
+
173
+ All the parameters are passed as environment variables.\
174
+ We need also to mount as volumes:
175
+ - the tests root folder : `-v $(pwd)/examples/tests:/opt/bigtesty/tests`
176
+ - the tables root folder: `-v $(pwd)/examples/tests/tables:/opt/bigtesty/tests/tables`
177
+ - the `gcloud` configuration: `-v $HOME/.config/gcloud:/opt/bigtesty/.config/gcloud`
178
+
179
+ When the authentication is done with Applications Default Credentials via the following command `gcloud auth application-default login`,\
180
+ a short-lived credential is generated in the local `gcloud` configuration: `$HOME/.config/gcloud`
181
+
182
+ To prevent the use of a long-lived SA token key, we can share and mount as volume the local `gcloud` configuration with the `Docker` container: `-v $HOME/.config/gcloud:/opt/bigtesty/.config/gcloud`\
183
+ With this technic, the container will be authenticated in Google Cloud securely, with your current user in the Shell session.
184
+
185
+ ### Run with Cloud Build
186
+
187
+ ```bash
188
+ export PROJECT_ID={{project_id}}
189
+ export LOCATION={{region}}
190
+ export IAC_BACKEND_URL=gs://{{gcs_state_bucket}}/bigtesty
191
+
192
+ gcloud builds submit \
193
+ --project=$PROJECT_ID \
194
+ --region=$LOCATION \
195
+ --config examples/ci/cloud_build/run-tests-cloud-build.yaml \
196
+ --substitutions _IAC_BACKEND_URL=$IAC_BACKEND_URL \
197
+ --verbosity="debug" .
198
+ ```
199
+
200
+ ## Contributing
201
+
202
+ cf. [CONTRIBUTING](CONTRIBUTING.md).
File without changes
@@ -0,0 +1,7 @@
1
+ import argparse
2
+
3
+ parser = argparse.ArgumentParser()
4
+ parser.add_argument('--root_folder', dest='root_folder', type=str, help='Root folder')
5
+ parser.add_argument('--project_id', dest='project_id', type=str, help='GCP Project ID')
6
+ parser.add_argument('--datasets_hash', dest='datasets_hash', type=str, help='Unique hash to isolate datasets')
7
+ args = parser.parse_args()
File without changes
@@ -0,0 +1,13 @@
1
+ GOOGLE_PROJECT_KEY = "GOOGLE_PROJECT"
2
+ GOOGLE_REGION_KEY = "GOOGLE_REGION"
3
+ IAC_BACKEND_URL_KEY = "IAC_BACKEND_URL"
4
+ ROOT_TEST_FOLDER_KEY = "ROOT_TEST_FOLDER"
5
+ ROOT_TABLES_FOLDER_KEY = "ROOT_TABLES_FOLDER"
6
+ TABLES_CONFIG_FILE_KEY = "TABLES_CONFIG_FILE"
7
+ KEEP_INFRA_KEY = "KEEP_INFRA"
8
+ BIGTESTY_STACK_NAME_KEY = "BIGTESTY_STACK_NAME"
9
+ PULUMI_CONFIG_PASSPHRASE_KEY = "PULUMI_CONFIG_PASSPHRASE"
10
+ PULUMI_BACKEND_URL_KEY = "PULUMI_BACKEND_URL"
11
+
12
+ BIGTESTY_STACK_NAME_VALUE = "bigtesty"
13
+ PULUMI_CONFIG_PASSPHRASE_VALUE = "gcp_fake_passphrase"
@@ -0,0 +1,102 @@
1
+ import os
2
+
3
+ import typer
4
+ from typing_extensions import Annotated
5
+
6
+ from bigtesty.cli.cli_env_vars import ROOT_TEST_FOLDER_KEY, ROOT_TABLES_FOLDER_KEY, TABLES_CONFIG_FILE_KEY, \
7
+ KEEP_INFRA_KEY, BIGTESTY_STACK_NAME_KEY, PULUMI_CONFIG_PASSPHRASE_KEY, PULUMI_BACKEND_URL_KEY, IAC_BACKEND_URL_KEY, \
8
+ BIGTESTY_STACK_NAME_VALUE, PULUMI_CONFIG_PASSPHRASE_VALUE, GOOGLE_PROJECT_KEY, GOOGLE_REGION_KEY
9
+ from bigtesty.infra.launch_tests_ephemeral_infra import launch_tests_ephemeral_infra
10
+
11
+ app = typer.Typer()
12
+
13
+
14
+ @app.command("test", help="Run tests")
15
+ def run_tests(
16
+ project: Annotated[
17
+ str,
18
+ typer.Option(
19
+ "--project",
20
+ envvar=GOOGLE_PROJECT_KEY,
21
+ help="GCP project ID."
22
+ )
23
+ ],
24
+ region: Annotated[
25
+ str,
26
+ typer.Option(
27
+ "--region",
28
+ envvar=GOOGLE_REGION_KEY,
29
+ help="GCP region."
30
+ )
31
+ ],
32
+ iac_backend_url: Annotated[
33
+ str,
34
+ typer.Option(
35
+ "--iac-backend-url",
36
+ envvar=IAC_BACKEND_URL_KEY,
37
+ help="IaC backend URL for the ephemeral infra used for the tests."
38
+ )
39
+ ],
40
+ root_test_folder: Annotated[
41
+ str,
42
+ typer.Option(
43
+ "--root-test-folder",
44
+ envvar=ROOT_TEST_FOLDER_KEY,
45
+ help="Directory that contains test scenarios."
46
+ )
47
+ ],
48
+ root_tables_folder: Annotated[
49
+ str,
50
+ typer.Option(
51
+ "--root-tables-folder",
52
+ envvar=ROOT_TABLES_FOLDER_KEY,
53
+ help="Directory that contains schema files."
54
+ )
55
+ ],
56
+ tables_config_file_path: Annotated[
57
+ str,
58
+ typer.Option(
59
+ "--tables-config-file",
60
+ envvar=TABLES_CONFIG_FILE_KEY,
61
+ help="Path to configuration file."
62
+ )
63
+ ],
64
+ keep_infra: Annotated[
65
+ bool,
66
+ typer.Option(
67
+ "--keep-infra",
68
+ envvar=KEEP_INFRA_KEY,
69
+ help="Keep infrastructure after exit."
70
+ )
71
+ ] = False):
72
+ print(f"####################### The CLI is invoked with params : ")
73
+
74
+ print(f"project : {project}")
75
+ print(f"region : {region}")
76
+ print(f"iac-backend-url : {iac_backend_url}")
77
+ print(f"root-test-folder : {root_test_folder}")
78
+ print(f"root-tables-folder : {root_tables_folder}")
79
+ print(f"tables-config-file : {tables_config_file_path}")
80
+ print(f"keep-infra : {keep_infra}")
81
+
82
+ os.environ[GOOGLE_PROJECT_KEY] = project
83
+ os.environ[GOOGLE_REGION_KEY] = region
84
+ os.environ[PULUMI_BACKEND_URL_KEY] = iac_backend_url
85
+ os.environ[PULUMI_CONFIG_PASSPHRASE_KEY] = PULUMI_CONFIG_PASSPHRASE_VALUE
86
+ os.environ[BIGTESTY_STACK_NAME_KEY] = BIGTESTY_STACK_NAME_VALUE
87
+
88
+ launch_tests_ephemeral_infra(
89
+ root_test_folder=root_test_folder,
90
+ root_tables_folder=root_tables_folder,
91
+ tables_config_file_path=tables_config_file_path,
92
+ keep_infra=keep_infra
93
+ )
94
+
95
+
96
+ @app.command("help")
97
+ def help():
98
+ print("BigTesty is an integration testing framework for BigQuery")
99
+
100
+
101
+ def run():
102
+ app()
@@ -0,0 +1,4 @@
1
+ def build_unique_dataset_id_for_scenario(dataset_id: str,
2
+ scenario_hash: str,
3
+ datasets_hash: str) -> str:
4
+ return f'{dataset_id}_{scenario_hash}_{datasets_hash}'
@@ -0,0 +1,57 @@
1
+ import glob
2
+ import json
3
+ from typing import List, Dict
4
+
5
+ from deepdiff import DeepHash
6
+
7
+ from bigtesty.definition_test_file_exception import DefinitionTestFileException
8
+ from bigtesty.lambda_functions import flat_map
9
+
10
+ DEFINITION_TEST_FILE_PATTERN = "**/definition_*.json"
11
+
12
+
13
+ def get_definition_test_dicts_from_path(data_testing_root_path: str) -> List[Dict]:
14
+ """
15
+ Gets all the test definition files existing in the given folder path and then map them to dicts.
16
+ The result is a list of dict, and each dict represents a test definition.
17
+ If there is no definition files in the given folder, a :class:`~DefinitionTestFileException` is raised.
18
+ :param data_testing_root_path: the root folder path containing test definition files
19
+ :return: a list of test definition dict
20
+ """
21
+ print("#############ROOT DIR")
22
+ print(data_testing_root_path)
23
+
24
+ definition_test_file_paths: List[str] = get_definition_tests_file_paths(data_testing_root_path)
25
+
26
+ if not definition_test_file_paths:
27
+ raise DefinitionTestFileException(
28
+ f'There is no definition files in the given folder path {data_testing_root_path}'
29
+ )
30
+
31
+ return list(map(lambda path: to_definition_test_dict(path), definition_test_file_paths))
32
+
33
+
34
+ def get_scenarios(data_testing_root_path: str):
35
+ return list(
36
+ flat_map(lambda deftest: deftest['scenarios'], get_definition_test_dicts_from_path(data_testing_root_path))
37
+ )
38
+
39
+
40
+ def get_definition_tests_file_paths(data_testing_root_path: str) -> List[str]:
41
+ """
42
+ Gets all the test definitions file paths existing in the given folder path.
43
+ The search of files is recursive.
44
+ """
45
+ return glob.glob(
46
+ pathname=f'{data_testing_root_path}/{DEFINITION_TEST_FILE_PATTERN}',
47
+ recursive=True
48
+ )
49
+
50
+
51
+ def to_definition_test_dict(definition_test_file_path: str):
52
+ with open(definition_test_file_path) as definition_test_file:
53
+ return json.load(definition_test_file)
54
+
55
+
56
+ def get_scenario_hash(scenario_dict: Dict) -> str:
57
+ return DeepHash(scenario_dict)[scenario_dict]
@@ -0,0 +1,2 @@
1
+ class DefinitionTestFileException(Exception):
2
+ pass
@@ -0,0 +1,12 @@
1
+ import json
2
+ from typing import List, Dict
3
+
4
+
5
+ def load_file_as_dicts(file_path: str) -> List[Dict]:
6
+ with open(file_path) as file:
7
+ return json.load(file)
8
+
9
+
10
+ def load_file_as_string(file_path: str) -> str:
11
+ with open(file_path, 'r') as file:
12
+ return file.read().rstrip()
File without changes