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.
- bigtesty-0.1.0/LICENSE +21 -0
- bigtesty-0.1.0/PKG-INFO +220 -0
- bigtesty-0.1.0/README.md +202 -0
- bigtesty-0.1.0/bigtesty/__init__.py +0 -0
- bigtesty-0.1.0/bigtesty/arguments.py +7 -0
- bigtesty-0.1.0/bigtesty/cli/__init__.py +0 -0
- bigtesty-0.1.0/bigtesty/cli/cli_env_vars.py +13 -0
- bigtesty-0.1.0/bigtesty/cli/main.py +102 -0
- bigtesty-0.1.0/bigtesty/dataset_helper.py +4 -0
- bigtesty-0.1.0/bigtesty/definition_test_config_helper.py +57 -0
- bigtesty-0.1.0/bigtesty/definition_test_file_exception.py +2 -0
- bigtesty-0.1.0/bigtesty/files_loader_helper.py +12 -0
- bigtesty-0.1.0/bigtesty/given/__init__.py +0 -0
- bigtesty-0.1.0/bigtesty/given/insertion_test_data_bigquery.py +43 -0
- bigtesty-0.1.0/bigtesty/infra/__init__.py +0 -0
- bigtesty-0.1.0/bigtesty/infra/create_iac_for_datasets_with_tables.py +50 -0
- bigtesty-0.1.0/bigtesty/infra/datasets_with_tables_config_file_loader.py +28 -0
- bigtesty-0.1.0/bigtesty/infra/datasets_with_tables_factory.py +55 -0
- bigtesty-0.1.0/bigtesty/infra/launch_tests_ephemeral_infra.py +134 -0
- bigtesty-0.1.0/bigtesty/lambda_functions.py +1 -0
- bigtesty-0.1.0/bigtesty/then/__init__.py +0 -0
- bigtesty-0.1.0/bigtesty/then/assertion_and_tests_reports_result.py +227 -0
- bigtesty-0.1.0/bigtesty/then/assertion_types.py +6 -0
- bigtesty-0.1.0/bigtesty/then/failure_test_exception.py +2 -0
- bigtesty-0.1.0/bigtesty.egg-info/PKG-INFO +220 -0
- bigtesty-0.1.0/bigtesty.egg-info/SOURCES.txt +30 -0
- bigtesty-0.1.0/bigtesty.egg-info/dependency_links.txt +1 -0
- bigtesty-0.1.0/bigtesty.egg-info/entry_points.txt +4 -0
- bigtesty-0.1.0/bigtesty.egg-info/requires.txt +6 -0
- bigtesty-0.1.0/bigtesty.egg-info/top_level.txt +1 -0
- bigtesty-0.1.0/setup.cfg +4 -0
- 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.
|
bigtesty-0.1.0/PKG-INFO
ADDED
|
@@ -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
|
+

|
|
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
|
+

|
|
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
|
+
|
bigtesty-0.1.0/README.md
ADDED
|
@@ -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
|
+

|
|
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
|
+

|
|
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,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,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
|