recce-nightly 1.10.0.20250625__py3-none-any.whl → 1.30.0.20251221__py3-none-any.whl
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.
Potentially problematic release.
This version of recce-nightly might be problematic. Click here for more details.
- recce/VERSION +1 -1
- recce/__init__.py +5 -0
- recce/adapter/dbt_adapter/__init__.py +343 -245
- recce/apis/check_api.py +20 -14
- recce/apis/check_events_api.py +353 -0
- recce/apis/check_func.py +5 -5
- recce/apis/run_func.py +32 -3
- recce/artifact.py +76 -3
- recce/cli.py +705 -82
- recce/config.py +2 -2
- recce/connect_to_cloud.py +1 -1
- recce/core.py +3 -3
- recce/data/404/index.html +2 -0
- recce/data/404.html +2 -22
- recce/data/__next.@lineage.!KHNsb3Qp.__PAGE__.txt +7 -0
- recce/data/__next.@lineage.!KHNsb3Qp.txt +4 -0
- recce/data/__next.__PAGE__.txt +6 -0
- recce/data/__next._full.txt +32 -0
- recce/data/__next._head.txt +8 -0
- recce/data/__next._index.txt +14 -0
- recce/data/__next._tree.txt +8 -0
- recce/data/_next/static/chunks/025a7e3e3f9f40ae.js +1 -0
- recce/data/_next/static/chunks/0ce56d67ef5779ca.js +4 -0
- recce/data/_next/static/chunks/1a6a78780155dac7.js +48 -0
- recce/data/_next/static/chunks/1de8485918b9182a.css +2 -0
- recce/data/_next/static/chunks/1e4b1b50d1e34993.js +1 -0
- recce/data/_next/static/chunks/206d5d181e4c738e.js +1 -0
- recce/data/_next/static/chunks/2c357efc34c5b859.js +25 -0
- recce/data/_next/static/chunks/2e9d95d2d48c479c.js +1 -0
- recce/data/_next/static/chunks/2f016dc4a3edad2e.js +2 -0
- recce/data/_next/static/chunks/313251962d698f7c.js +1 -0
- recce/data/_next/static/chunks/3a9f021f38eb5574.css +1 -0
- recce/data/_next/static/chunks/40079da8d2b8f651.js +1 -0
- recce/data/_next/static/chunks/4599182bffb64661.js +38 -0
- recce/data/_next/static/chunks/4e62f6e184173580.js +1 -0
- recce/data/_next/static/chunks/5c4dfb0d09eaa401.js +1 -0
- recce/data/_next/static/chunks/69e4f06ccfdfc3ac.js +1 -0
- recce/data/_next/static/chunks/6b206cb4707d6bee.js +1 -0
- recce/data/_next/static/chunks/6d8557f062aa4386.css +1 -0
- recce/data/_next/static/chunks/7fbe3650bd83b6b5.js +1 -0
- recce/data/_next/static/chunks/83fa823a825674f6.js +1 -0
- recce/data/_next/static/chunks/848a6c9b5f55f7ed.js +1 -0
- recce/data/_next/static/chunks/859462b0858aef88.css +2 -0
- recce/data/_next/static/chunks/923964f18c87d0f1.css +1 -0
- recce/data/_next/static/chunks/939390f911895d7c.js +48 -0
- recce/data/_next/static/chunks/99a9817237a07f43.js +1 -0
- recce/data/_next/static/chunks/9fed8b4b2b924054.js +5 -0
- recce/data/_next/static/chunks/b6949f6c5892110c.js +1 -0
- recce/data/_next/static/chunks/b851a1d3f8149828.js +1 -0
- recce/data/_next/static/chunks/c734f9ad957de0b4.js +1 -0
- recce/data/_next/static/chunks/cdde321b0ec75717.js +2 -0
- recce/data/_next/static/chunks/d0f91117d77ff844.css +1 -0
- recce/data/_next/static/chunks/d6c8667911c2500f.js +1 -0
- recce/data/_next/static/chunks/da8dab68c02752cf.js +74 -0
- recce/data/_next/static/chunks/dc074049c9d12d97.js +109 -0
- recce/data/_next/static/chunks/ee7f1a8227342421.js +1 -0
- recce/data/_next/static/chunks/fa2f4e56c2fccc73.js +1 -0
- recce/data/_next/static/chunks/turbopack-1fad664f62979b93.js +3 -0
- recce/data/_next/static/media/favicon.a8d38d84.ico +0 -0
- recce/data/_next/static/media/montserrat-cyrillic-800-normal.d80d830d.woff2 +0 -0
- recce/data/_next/static/media/{montserrat-cyrillic-800-normal.bd5c9f50.woff → montserrat-cyrillic-800-normal.f9d58125.woff} +0 -0
- recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.076c2a93.woff2 +0 -0
- recce/data/_next/static/media/montserrat-latin-800-normal.cde454cc.woff2 +0 -0
- recce/data/_next/static/media/{montserrat-latin-800-normal.fc315020.woff → montserrat-latin-800-normal.d5761935.woff} +0 -0
- recce/data/_next/static/media/montserrat-latin-ext-800-normal.40ec0659.woff2 +0 -0
- recce/data/_next/static/media/{montserrat-latin-ext-800-normal.2e5381b2.woff → montserrat-latin-ext-800-normal.b671449b.woff} +0 -0
- recce/data/_next/static/media/{montserrat-vietnamese-800-normal.20c545e6.woff → montserrat-vietnamese-800-normal.9f7b8541.woff} +0 -0
- recce/data/_next/static/media/montserrat-vietnamese-800-normal.f9eb854e.woff2 +0 -0
- recce/data/_next/static/nX-Uz0AH6Tc6hIQUFGqaB/_buildManifest.js +11 -0
- recce/data/_next/static/nX-Uz0AH6Tc6hIQUFGqaB/_clientMiddlewareManifest.json +1 -0
- recce/data/_not-found/__next._full.txt +24 -0
- recce/data/_not-found/__next._head.txt +8 -0
- recce/data/_not-found/__next._index.txt +13 -0
- recce/data/_not-found/__next._not-found.__PAGE__.txt +5 -0
- recce/data/_not-found/__next._not-found.txt +4 -0
- recce/data/_not-found/__next._tree.txt +6 -0
- recce/data/_not-found/index.html +2 -0
- recce/data/_not-found/index.txt +24 -0
- recce/data/auth_callback.html +1 -1
- recce/data/checks/__next.@lineage.__DEFAULT__.txt +7 -0
- recce/data/checks/__next._full.txt +39 -0
- recce/data/checks/__next._head.txt +8 -0
- recce/data/checks/__next._index.txt +14 -0
- recce/data/checks/__next._tree.txt +8 -0
- recce/data/checks/__next.checks.__PAGE__.txt +10 -0
- recce/data/checks/__next.checks.txt +4 -0
- recce/data/checks/index.html +2 -0
- recce/data/checks/index.txt +39 -0
- recce/data/index.html +2 -27
- recce/data/index.txt +32 -8
- recce/data/lineage/__next.@lineage.__DEFAULT__.txt +7 -0
- recce/data/lineage/__next._full.txt +39 -0
- recce/data/lineage/__next._head.txt +8 -0
- recce/data/lineage/__next._index.txt +14 -0
- recce/data/lineage/__next._tree.txt +8 -0
- recce/data/lineage/__next.lineage.__PAGE__.txt +10 -0
- recce/data/lineage/__next.lineage.txt +4 -0
- recce/data/lineage/index.html +2 -0
- recce/data/lineage/index.txt +39 -0
- recce/data/query/__next.@lineage.__DEFAULT__.txt +7 -0
- recce/data/query/__next._full.txt +37 -0
- recce/data/query/__next._head.txt +8 -0
- recce/data/query/__next._index.txt +14 -0
- recce/data/query/__next._tree.txt +8 -0
- recce/data/query/__next.query.__PAGE__.txt +9 -0
- recce/data/query/__next.query.txt +4 -0
- recce/data/query/index.html +2 -0
- recce/data/query/index.txt +37 -0
- recce/event/CONFIG.bak +1 -0
- recce/event/__init__.py +9 -8
- recce/event/collector.py +6 -2
- recce/event/track.py +10 -0
- recce/github.py +1 -1
- recce/mcp_server.py +725 -0
- recce/models/check.py +433 -15
- recce/models/types.py +61 -2
- recce/pull_request.py +1 -1
- recce/run.py +37 -17
- recce/server.py +216 -21
- recce/state/__init__.py +31 -0
- recce/state/cloud.py +644 -0
- recce/state/const.py +26 -0
- recce/state/local.py +56 -0
- recce/state/state.py +119 -0
- recce/state/state_loader.py +174 -0
- recce/summary.py +25 -3
- recce/tasks/dataframe.py +63 -1
- recce/tasks/query.py +40 -3
- recce/tasks/rowcount.py +4 -1
- recce/tasks/schema.py +4 -1
- recce/tasks/utils.py +147 -0
- recce/tasks/valuediff.py +85 -57
- recce/util/api_token.py +11 -2
- recce/util/breaking.py +10 -1
- recce/util/cll.py +1 -2
- recce/util/cloud/__init__.py +15 -0
- recce/util/cloud/base.py +115 -0
- recce/util/cloud/check_events.py +190 -0
- recce/util/cloud/checks.py +242 -0
- recce/util/io.py +2 -2
- recce/util/lineage.py +19 -18
- recce/util/perf_tracking.py +85 -0
- recce/util/recce_cloud.py +254 -5
- recce/util/startup_perf.py +121 -0
- recce/yaml/__init__.py +2 -2
- {recce_nightly-1.10.0.20250625.dist-info → recce_nightly-1.30.0.20251221.dist-info}/METADATA +91 -71
- recce_nightly-1.30.0.20251221.dist-info/RECORD +183 -0
- {recce_nightly-1.10.0.20250625.dist-info → recce_nightly-1.30.0.20251221.dist-info}/WHEEL +1 -2
- recce/data/_next/static/abCX3x3UoIdRLEDWxx4xd/_buildManifest.js +0 -1
- recce/data/_next/static/chunks/181-acc61ddada3bc0ca.js +0 -43
- recce/data/_next/static/chunks/1bff33f1-1ef85cf5e658a751.js +0 -1
- recce/data/_next/static/chunks/217-879a84d70f7a907c.js +0 -2
- recce/data/_next/static/chunks/29e3cc0d-60045b2e47aa3916.js +0 -1
- recce/data/_next/static/chunks/36e1c10d-8e7be4a6c1f6ab2d.js +0 -1
- recce/data/_next/static/chunks/3998a672-03adacad07b346ac.js +0 -1
- recce/data/_next/static/chunks/3a92ee20-1081c360214f9602.js +0 -1
- recce/data/_next/static/chunks/42-cd3c06533f5fd47c.js +0 -9
- recce/data/_next/static/chunks/450c323b-fd94e7ffaa4a5efa.js +0 -1
- recce/data/_next/static/chunks/47d8844f-929aed9b1c73a905.js +0 -1
- recce/data/_next/static/chunks/608-3b079b544e5d5f5e.js +0 -15
- recce/data/_next/static/chunks/6dc81886-adbfa45836061d79.js +0 -1
- recce/data/_next/static/chunks/7a8a3e83-edf6dc64b5d5f0a5.js +0 -1
- recce/data/_next/static/chunks/7f27ae6c-d5f0438edd5c2a5b.js +0 -1
- recce/data/_next/static/chunks/86730205-cfb14e3f051bab35.js +0 -1
- recce/data/_next/static/chunks/8d700b6a.8bb140898499c512.js +0 -1
- recce/data/_next/static/chunks/92-607cd1af83c41f43.js +0 -1
- recce/data/_next/static/chunks/9746af58-a42b7d169cacadf0.js +0 -1
- recce/data/_next/static/chunks/a30376cd-de84559016d7e133.js +0 -1
- recce/data/_next/static/chunks/app/_not-found/page-01ed58b7f971d311.js +0 -1
- recce/data/_next/static/chunks/app/layout-177a410a97e0d018.js +0 -1
- recce/data/_next/static/chunks/app/page-da6e046a8235dbfc.js +0 -1
- recce/data/_next/static/chunks/b63b1b3f-4282bdcf459e075c.js +0 -1
- recce/data/_next/static/chunks/bbda5537-9ec25eb1dd62348a.js +0 -1
- recce/data/_next/static/chunks/c132bf7d-08cb668a789d6afd.js +0 -1
- recce/data/_next/static/chunks/ce84277d-2e5d1d46910cf052.js +0 -1
- recce/data/_next/static/chunks/febdd86e-c6b525341634b860.js +0 -54
- recce/data/_next/static/chunks/fee69bc6-2dbccaf9b90474e6.js +0 -1
- recce/data/_next/static/chunks/framework-ded83d71b51ce901.js +0 -1
- recce/data/_next/static/chunks/main-app-39061b0166c47f55.js +0 -1
- recce/data/_next/static/chunks/main-b5b3ae20a1405261.js +0 -1
- recce/data/_next/static/chunks/pages/_app-437c455677d62394.js +0 -1
- recce/data/_next/static/chunks/pages/_error-e7650df18ca04bde.js +0 -1
- recce/data/_next/static/chunks/webpack-7b49d5ba7e3a434d.js +0 -1
- recce/data/_next/static/css/17a96168e3a9db13.css +0 -1
- recce/data/_next/static/css/1b121dc4d36aeb4d.css +0 -3
- recce/data/_next/static/css/35c6679a098e1e34.css +0 -1
- recce/data/_next/static/css/951e2e0eea2d4a5b.css +0 -14
- recce/data/_next/static/media/montserrat-cyrillic-800-normal.22628180.woff2 +0 -0
- recce/data/_next/static/media/montserrat-cyrillic-ext-800-normal.94a63aea.woff2 +0 -0
- recce/data/_next/static/media/montserrat-latin-800-normal.6f8fa298.woff2 +0 -0
- recce/data/_next/static/media/montserrat-latin-ext-800-normal.013b84f9.woff2 +0 -0
- recce/data/_next/static/media/montserrat-vietnamese-800-normal.c0035377.woff2 +0 -0
- recce/data/_next/static/media/reload-image.79aabb7d.svg +0 -4
- recce/state.py +0 -786
- recce_nightly-1.10.0.20250625.dist-info/RECORD +0 -154
- recce_nightly-1.10.0.20250625.dist-info/top_level.txt +0 -2
- tests/__init__.py +0 -0
- tests/adapter/__init__.py +0 -0
- tests/adapter/dbt_adapter/__init__.py +0 -0
- tests/adapter/dbt_adapter/conftest.py +0 -17
- tests/adapter/dbt_adapter/dbt_test_helper.py +0 -298
- tests/adapter/dbt_adapter/test_dbt_adapter.py +0 -25
- tests/adapter/dbt_adapter/test_dbt_cll.py +0 -384
- tests/adapter/dbt_adapter/test_selector.py +0 -202
- tests/tasks/__init__.py +0 -0
- tests/tasks/conftest.py +0 -4
- tests/tasks/test_histogram.py +0 -129
- tests/tasks/test_lineage.py +0 -55
- tests/tasks/test_preset_checks.py +0 -64
- tests/tasks/test_profile.py +0 -397
- tests/tasks/test_query.py +0 -151
- tests/tasks/test_row_count.py +0 -135
- tests/tasks/test_schema.py +0 -122
- tests/tasks/test_top_k.py +0 -77
- tests/tasks/test_valuediff.py +0 -85
- tests/test_cli.py +0 -133
- tests/test_config.py +0 -43
- tests/test_connect_to_cloud.py +0 -82
- tests/test_core.py +0 -29
- tests/test_dbt.py +0 -36
- tests/test_pull_request.py +0 -130
- tests/test_server.py +0 -104
- tests/test_state.py +0 -134
- tests/test_summary.py +0 -65
- /recce/data/_next/static/chunks/{polyfills-42372ed130431b0a.js → a6dad97d9634a72d.js} +0 -0
- /recce/data/_next/static/media/{montserrat-cyrillic-ext-800-normal.e6e0d8d0.woff → montserrat-cyrillic-ext-800-normal.a4fa76b5.woff} +0 -0
- /recce/data/_next/static/{abCX3x3UoIdRLEDWxx4xd → nX-Uz0AH6Tc6hIQUFGqaB}/_ssgManifest.js +0 -0
- {recce_nightly-1.10.0.20250625.dist-info → recce_nightly-1.30.0.20251221.dist-info}/entry_points.txt +0 -0
- {recce_nightly-1.10.0.20250625.dist-info → recce_nightly-1.30.0.20251221.dist-info}/licenses/LICENSE +0 -0
tests/tasks/test_query.py
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
from recce.tasks import QueryDiffTask, QueryTask
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def test_query_diff_in_client(dbt_test_helper):
|
|
7
|
-
csv_data_curr = """
|
|
8
|
-
customer_id,name,age
|
|
9
|
-
1,Alice,30
|
|
10
|
-
2,Bob,25
|
|
11
|
-
3,Charlie,35
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
csv_data_base = """
|
|
15
|
-
customer_id,name,age
|
|
16
|
-
1,Alice,35
|
|
17
|
-
2,Bob,25
|
|
18
|
-
3,Charlie,35
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr)
|
|
22
|
-
params = dict(sql_template='select * from {{ ref("customers") }}')
|
|
23
|
-
task = QueryTask(params)
|
|
24
|
-
run_result = task.execute()
|
|
25
|
-
assert len(run_result.current.data) == 3
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def test_query_diff_in_client(dbt_test_helper):
|
|
29
|
-
csv_data_curr = """
|
|
30
|
-
customer_id,name,age
|
|
31
|
-
1,Alice,30
|
|
32
|
-
2,Bob,25
|
|
33
|
-
3,Charlie,35
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
csv_data_base = """
|
|
37
|
-
customer_id,name,age
|
|
38
|
-
1,Alice,35
|
|
39
|
-
2,Bob,25
|
|
40
|
-
3,Charlie,35
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr)
|
|
44
|
-
params = dict(sql_template='select * from {{ ref("customers") }}')
|
|
45
|
-
task = QueryDiffTask(params)
|
|
46
|
-
run_result = task.execute()
|
|
47
|
-
assert len(run_result.base.data) == 3
|
|
48
|
-
assert len(run_result.current.data) == 3
|
|
49
|
-
|
|
50
|
-
params = dict(
|
|
51
|
-
base_sql_template='select * from {{ ref("customers") }} where customer_id <= 2',
|
|
52
|
-
sql_template='select * from {{ ref("customers") }}',
|
|
53
|
-
)
|
|
54
|
-
task = QueryDiffTask(params)
|
|
55
|
-
run_result = task.execute()
|
|
56
|
-
assert len(run_result.base.data) == 2
|
|
57
|
-
assert len(run_result.current.data) == 3
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def test_query_diff_in_warehouse(dbt_test_helper):
|
|
61
|
-
csv_data_curr = """
|
|
62
|
-
customer_id,name,age
|
|
63
|
-
1,Alice,30
|
|
64
|
-
2,Bob,25
|
|
65
|
-
3,Charlie,35
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
csv_data_base = """
|
|
69
|
-
customer_id,name,age
|
|
70
|
-
1,Alice,35
|
|
71
|
-
2,Bob,25
|
|
72
|
-
3,Charlie,35
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr)
|
|
76
|
-
params = dict(sql_template='select * from {{ ref("customers") }}', primary_keys=["customer_id"])
|
|
77
|
-
task = QueryDiffTask(params)
|
|
78
|
-
run_result = task.execute()
|
|
79
|
-
assert len(run_result.diff.data) == 2
|
|
80
|
-
|
|
81
|
-
params = dict(
|
|
82
|
-
base_sql_template='select * from {{ ref("customers") }} where customer_id == 1',
|
|
83
|
-
sql_template='select * from {{ ref("customers") }}',
|
|
84
|
-
primary_keys=["customer_id"],
|
|
85
|
-
)
|
|
86
|
-
task = QueryDiffTask(params)
|
|
87
|
-
run_result = task.execute()
|
|
88
|
-
assert len(run_result.diff.data) == 4
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def test_validator():
|
|
92
|
-
from recce.tasks.query import QueryCheckValidator, QueryDiffCheckValidator
|
|
93
|
-
|
|
94
|
-
def validate(params: dict = {}, view_options: dict = {}):
|
|
95
|
-
QueryCheckValidator().validate(
|
|
96
|
-
{
|
|
97
|
-
"name": "test",
|
|
98
|
-
"type": "query",
|
|
99
|
-
"params": params,
|
|
100
|
-
"view_options": view_options,
|
|
101
|
-
}
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
def validate_diff(params: dict = {}, view_options: dict = {}):
|
|
105
|
-
QueryDiffCheckValidator().validate(
|
|
106
|
-
{
|
|
107
|
-
"name": "test",
|
|
108
|
-
"type": "query_diff",
|
|
109
|
-
"params": params,
|
|
110
|
-
"view_options": view_options,
|
|
111
|
-
}
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
# query
|
|
115
|
-
validate({"sql_template": "select * from abc"})
|
|
116
|
-
|
|
117
|
-
# diff in client
|
|
118
|
-
validate_diff({"sql_template": "select * from abc"})
|
|
119
|
-
validate_diff(
|
|
120
|
-
{
|
|
121
|
-
"sql_template": "select * from abc",
|
|
122
|
-
"base_sql_template": "select * from abc",
|
|
123
|
-
}
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
# diff in warehouse
|
|
127
|
-
validate_diff(
|
|
128
|
-
{
|
|
129
|
-
"primary_keys": ["customer_id"],
|
|
130
|
-
"sql_template": "select * from abc",
|
|
131
|
-
}
|
|
132
|
-
)
|
|
133
|
-
validate_diff(
|
|
134
|
-
{"sql_template": "select * from abc", "base_sql_template": "select * from abc", "primary_keys": ["customer_id"]}
|
|
135
|
-
)
|
|
136
|
-
validate_diff(
|
|
137
|
-
{"sql_template": "select * from abc", "base_sql_template": "select * from abc", "primary_keys": ["customer_id"]}
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
# invalid
|
|
141
|
-
with pytest.raises(ValueError):
|
|
142
|
-
validate()
|
|
143
|
-
|
|
144
|
-
with pytest.raises(ValueError):
|
|
145
|
-
validate_diff()
|
|
146
|
-
|
|
147
|
-
with pytest.raises(ValueError):
|
|
148
|
-
validate_diff({"sql_template": 123, "primary_keys": "xyz"})
|
|
149
|
-
|
|
150
|
-
with pytest.raises(ValueError):
|
|
151
|
-
validate_diff({"sql_template": "s", "primary_keys": "xyz"})
|
tests/tasks/test_row_count.py
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
from recce.tasks import RowCountDiffTask
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def test_row_count(dbt_test_helper):
|
|
7
|
-
csv_data_curr = """
|
|
8
|
-
customer_id,name,age
|
|
9
|
-
1,Alice,30
|
|
10
|
-
2,Bob,25
|
|
11
|
-
3,Charlie,35
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
csv_data_base = """
|
|
15
|
-
customer_id,name,age
|
|
16
|
-
1,Alice,35
|
|
17
|
-
2,Bob,25
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr, unique_id="model.customers")
|
|
21
|
-
task = RowCountDiffTask(dict(node_names=["customers"]))
|
|
22
|
-
run_result = task.execute()
|
|
23
|
-
assert run_result["customers"]["base"] == 2
|
|
24
|
-
assert run_result["customers"]["curr"] == 3
|
|
25
|
-
|
|
26
|
-
task = RowCountDiffTask(dict(node_names=["customers_"]))
|
|
27
|
-
run_result = task.execute()
|
|
28
|
-
assert run_result["customers_"]["base"] is None
|
|
29
|
-
assert run_result["customers_"]["curr"] is None
|
|
30
|
-
|
|
31
|
-
task = RowCountDiffTask(dict(node_ids=["model.customers"]))
|
|
32
|
-
run_result = task.execute()
|
|
33
|
-
assert run_result["customers"]["base"] == 2
|
|
34
|
-
assert run_result["customers"]["curr"] == 3
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def test_row_count_with_selector(dbt_test_helper):
|
|
38
|
-
csv_data_1 = """
|
|
39
|
-
customer_id,name,age
|
|
40
|
-
1,Alice,30
|
|
41
|
-
2,Bob,25
|
|
42
|
-
3,Charlie,35
|
|
43
|
-
"""
|
|
44
|
-
|
|
45
|
-
csv_data_2 = """
|
|
46
|
-
customer_id,name,age
|
|
47
|
-
1,Alice,35
|
|
48
|
-
2,Bob,25
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
dbt_test_helper.create_model("model_1", csv_data_1, csv_data_2, depends_on=[])
|
|
52
|
-
dbt_test_helper.create_model(
|
|
53
|
-
"model_2", csv_data_1, csv_data_1, depends_on=["model_1"], package_name="other_package"
|
|
54
|
-
)
|
|
55
|
-
task = RowCountDiffTask(dict(select="model_1"))
|
|
56
|
-
run_result = task.execute()
|
|
57
|
-
assert len(run_result) == 1
|
|
58
|
-
|
|
59
|
-
task = RowCountDiffTask(dict(select="model_1+"))
|
|
60
|
-
run_result = task.execute()
|
|
61
|
-
assert len(run_result) == 2
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def test_validator():
|
|
65
|
-
from recce.tasks.rowcount import RowCountDiffCheckValidator
|
|
66
|
-
|
|
67
|
-
validator = RowCountDiffCheckValidator()
|
|
68
|
-
|
|
69
|
-
def validate(params: dict):
|
|
70
|
-
validator.validate(
|
|
71
|
-
{
|
|
72
|
-
"name": "test",
|
|
73
|
-
"type": "row_count_diff",
|
|
74
|
-
"params": params,
|
|
75
|
-
}
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
# Select all modesl
|
|
79
|
-
validate({})
|
|
80
|
-
|
|
81
|
-
# Select by node name
|
|
82
|
-
validate(
|
|
83
|
-
{
|
|
84
|
-
"node_names": ["abc"],
|
|
85
|
-
}
|
|
86
|
-
)
|
|
87
|
-
with pytest.raises(ValueError):
|
|
88
|
-
validate(
|
|
89
|
-
{
|
|
90
|
-
"node_names": "abc",
|
|
91
|
-
}
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
# Select by node id
|
|
95
|
-
validate(
|
|
96
|
-
{
|
|
97
|
-
"node_ids": ["model.abc"],
|
|
98
|
-
}
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
# Select by selector
|
|
102
|
-
validate(
|
|
103
|
-
{
|
|
104
|
-
"select": "customers",
|
|
105
|
-
"exclude": "customers",
|
|
106
|
-
"packages": ["jaffle_shop"],
|
|
107
|
-
"view_mode": "all",
|
|
108
|
-
}
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
# packages should be an array
|
|
112
|
-
with pytest.raises(ValueError):
|
|
113
|
-
validate(
|
|
114
|
-
{
|
|
115
|
-
"packages": "jaffle_shop",
|
|
116
|
-
}
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
# view_mode should be 'all' or 'changed_models'
|
|
120
|
-
validate(
|
|
121
|
-
{
|
|
122
|
-
"view_mode": None,
|
|
123
|
-
}
|
|
124
|
-
)
|
|
125
|
-
validate(
|
|
126
|
-
{
|
|
127
|
-
"view_mode": "all",
|
|
128
|
-
}
|
|
129
|
-
)
|
|
130
|
-
with pytest.raises(ValueError):
|
|
131
|
-
validate(
|
|
132
|
-
{
|
|
133
|
-
"view_mode": "abc",
|
|
134
|
-
}
|
|
135
|
-
)
|
tests/tasks/test_schema.py
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from unittest import TestCase
|
|
3
|
-
from unittest.mock import MagicMock
|
|
4
|
-
|
|
5
|
-
import pytest
|
|
6
|
-
|
|
7
|
-
from recce.adapter.dbt_adapter import DbtAdapter, load_catalog, load_manifest
|
|
8
|
-
from recce.core import RecceContext, set_default_context
|
|
9
|
-
from recce.run import schema_diff_should_be_approved
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def test_validator():
|
|
13
|
-
from recce.tasks.schema import SchemaDiffCheckValidator
|
|
14
|
-
|
|
15
|
-
validator = SchemaDiffCheckValidator()
|
|
16
|
-
|
|
17
|
-
def validate(params: dict):
|
|
18
|
-
validator.validate(
|
|
19
|
-
{
|
|
20
|
-
"name": "test",
|
|
21
|
-
"type": "schema_diff",
|
|
22
|
-
"params": params,
|
|
23
|
-
}
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
# Select all models
|
|
27
|
-
validate({})
|
|
28
|
-
|
|
29
|
-
# Select by node name
|
|
30
|
-
validate(
|
|
31
|
-
{
|
|
32
|
-
"node_id": "abc",
|
|
33
|
-
}
|
|
34
|
-
)
|
|
35
|
-
validate(
|
|
36
|
-
{
|
|
37
|
-
"node_id": ["abc"],
|
|
38
|
-
}
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
# Select by selector
|
|
42
|
-
validate(
|
|
43
|
-
{
|
|
44
|
-
"select": "customers",
|
|
45
|
-
"exclude": "customers",
|
|
46
|
-
"packages": ["jaffle_shop"],
|
|
47
|
-
"view_mode": "all",
|
|
48
|
-
}
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
# packages should be an array
|
|
52
|
-
with pytest.raises(ValueError):
|
|
53
|
-
validate(
|
|
54
|
-
{
|
|
55
|
-
"packages": "jaffle_shop",
|
|
56
|
-
}
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
# view_mode should be 'all' or 'changed_models'
|
|
60
|
-
validate(
|
|
61
|
-
{
|
|
62
|
-
"view_mode": None,
|
|
63
|
-
}
|
|
64
|
-
)
|
|
65
|
-
validate(
|
|
66
|
-
{
|
|
67
|
-
"view_mode": "all",
|
|
68
|
-
}
|
|
69
|
-
)
|
|
70
|
-
with pytest.raises(ValueError):
|
|
71
|
-
validate(
|
|
72
|
-
{
|
|
73
|
-
"view_mode": "abc",
|
|
74
|
-
}
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
test_root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
class TestSchemaDiffAutoApprove(TestCase):
|
|
82
|
-
|
|
83
|
-
def setUp(self):
|
|
84
|
-
self.default_context = MagicMock(spec=RecceContext)
|
|
85
|
-
manifest = load_manifest(path=os.path.join(test_root_path, "manifest.json"))
|
|
86
|
-
catalog = load_catalog(path=os.path.join(test_root_path, "catalog.json"))
|
|
87
|
-
dbt_adapter = DbtAdapter(curr_manifest=manifest, curr_catalog=catalog)
|
|
88
|
-
self.default_context.adapter = dbt_adapter
|
|
89
|
-
|
|
90
|
-
dbt_adapter.adapter = MagicMock()
|
|
91
|
-
dbt_adapter.adapter.type.return_value = None
|
|
92
|
-
|
|
93
|
-
dbt_adapter.select_nodes = MagicMock()
|
|
94
|
-
# Base and Current will be the same
|
|
95
|
-
self.default_context.get_lineage.return_value = dbt_adapter.get_lineage()
|
|
96
|
-
set_default_context(self.default_context)
|
|
97
|
-
|
|
98
|
-
def test_schema_diff_should_be_approved(self):
|
|
99
|
-
# Node_id is string
|
|
100
|
-
is_approved = schema_diff_should_be_approved(
|
|
101
|
-
{
|
|
102
|
-
"node_id": "model.jaffle_shop.customers",
|
|
103
|
-
}
|
|
104
|
-
)
|
|
105
|
-
assert is_approved is True
|
|
106
|
-
|
|
107
|
-
# Node_id is list
|
|
108
|
-
is_approved = schema_diff_should_be_approved(
|
|
109
|
-
{
|
|
110
|
-
"node_id": ["model.jaffle_shop.customers"],
|
|
111
|
-
}
|
|
112
|
-
)
|
|
113
|
-
assert is_approved is True
|
|
114
|
-
|
|
115
|
-
# Select all models
|
|
116
|
-
self.default_context.adapter.select_nodes.return_value = ["model.jaffle_shop.customers"]
|
|
117
|
-
is_approved = schema_diff_should_be_approved(
|
|
118
|
-
{
|
|
119
|
-
"select": "customers",
|
|
120
|
-
}
|
|
121
|
-
)
|
|
122
|
-
assert is_approved is True
|
tests/tasks/test_top_k.py
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
from recce.tasks import TopKDiffTask
|
|
4
|
-
from recce.tasks.top_k import TopKDiffCheckValidator
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def test_top_k(dbt_test_helper):
|
|
8
|
-
csv_data_curr = """
|
|
9
|
-
customer_id,name,age
|
|
10
|
-
1,Alice,30
|
|
11
|
-
2,Bob,25
|
|
12
|
-
3,Charlie,35
|
|
13
|
-
4,Bob,35
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
csv_data_base = """
|
|
17
|
-
customer_id,name,age
|
|
18
|
-
1,Alice,35
|
|
19
|
-
2,Bob,25
|
|
20
|
-
3,Charlie,35
|
|
21
|
-
4,,35
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr)
|
|
25
|
-
|
|
26
|
-
params = dict(
|
|
27
|
-
model="customers",
|
|
28
|
-
column_name="name",
|
|
29
|
-
k=50,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
task = TopKDiffTask(params)
|
|
33
|
-
run_result = task.execute()
|
|
34
|
-
|
|
35
|
-
# {
|
|
36
|
-
# 'values': ['Bob', 'Alice', 'Charlie'],
|
|
37
|
-
# 'counts': [2, 1, 1],
|
|
38
|
-
# 'valids': 4,
|
|
39
|
-
# 'total': 4
|
|
40
|
-
# }
|
|
41
|
-
assert run_result["current"]["values"][0] == "Bob"
|
|
42
|
-
assert run_result["current"]["counts"][0] == 2
|
|
43
|
-
assert run_result["current"]["valids"] == 4
|
|
44
|
-
assert run_result["current"]["total"] == 4
|
|
45
|
-
|
|
46
|
-
# {
|
|
47
|
-
# 'values': ['Bob', 'Alice', 'Charlie'],
|
|
48
|
-
# 'counts': [1, 1, 1],
|
|
49
|
-
# 'valids': 3,
|
|
50
|
-
# 'total': 4
|
|
51
|
-
# }
|
|
52
|
-
assert run_result["base"]["counts"][0] == 1
|
|
53
|
-
assert run_result["base"]["valids"] == 3
|
|
54
|
-
assert run_result["base"]["total"] == 4
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def test_validator():
|
|
58
|
-
def validate(params: dict = {}, view_options: dict = {}):
|
|
59
|
-
TopKDiffCheckValidator().validate(
|
|
60
|
-
{
|
|
61
|
-
"name": "test",
|
|
62
|
-
"type": "top_k_diff",
|
|
63
|
-
"params": params,
|
|
64
|
-
"view_options": view_options,
|
|
65
|
-
}
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
validate(
|
|
69
|
-
{
|
|
70
|
-
"model": "customers",
|
|
71
|
-
"column_name": "name",
|
|
72
|
-
"k": 50,
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
with pytest.raises(ValueError):
|
|
77
|
-
validate({})
|
tests/tasks/test_valuediff.py
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
|
|
3
|
-
from recce.tasks import ValueDiffDetailTask, ValueDiffTask
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def test_value_diff(dbt_test_helper):
|
|
7
|
-
csv_data_curr = """
|
|
8
|
-
customer_id,name,age
|
|
9
|
-
1,Alice,30
|
|
10
|
-
2,Bob,25
|
|
11
|
-
3,Charlie,35
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
csv_data_base = """
|
|
15
|
-
customer_id,name,age
|
|
16
|
-
1,Alice,35
|
|
17
|
-
2,Bob,25
|
|
18
|
-
3,Charlie,35
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
dbt_test_helper.create_model("customers", csv_data_base, csv_data_curr)
|
|
22
|
-
params = dict(model="customers", primary_key=["customer_id"])
|
|
23
|
-
task = ValueDiffTask(params)
|
|
24
|
-
run_result = task.execute()
|
|
25
|
-
assert len(run_result.data.columns) == 3
|
|
26
|
-
assert len(run_result.data.data) == 3
|
|
27
|
-
|
|
28
|
-
params = dict(model="customers", primary_key=["customer_id"])
|
|
29
|
-
task = ValueDiffDetailTask(params)
|
|
30
|
-
run_result = task.execute()
|
|
31
|
-
assert len(run_result.columns) == 5
|
|
32
|
-
assert len(run_result.data) == 2
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def test_validator():
|
|
36
|
-
from recce.tasks.valuediff import ValueDiffCheckValidator
|
|
37
|
-
|
|
38
|
-
def validate(params: dict = {}, view_options: dict = {}):
|
|
39
|
-
ValueDiffCheckValidator().validate(
|
|
40
|
-
{
|
|
41
|
-
"name": "test",
|
|
42
|
-
"type": "value_diff",
|
|
43
|
-
"params": params,
|
|
44
|
-
"view_options": view_options,
|
|
45
|
-
}
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
validate(
|
|
49
|
-
{
|
|
50
|
-
"model": "customers",
|
|
51
|
-
"primary_key": "customer_id",
|
|
52
|
-
}
|
|
53
|
-
)
|
|
54
|
-
validate(
|
|
55
|
-
{
|
|
56
|
-
"model": "customers",
|
|
57
|
-
"primary_key": ["customer_id"],
|
|
58
|
-
}
|
|
59
|
-
)
|
|
60
|
-
validate(
|
|
61
|
-
{
|
|
62
|
-
"model": "customers",
|
|
63
|
-
"primary_key": ["customer_id"],
|
|
64
|
-
"columns": ["name", "age"],
|
|
65
|
-
}
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
with pytest.raises(ValueError):
|
|
69
|
-
validate({})
|
|
70
|
-
|
|
71
|
-
with pytest.raises(ValueError):
|
|
72
|
-
validate(
|
|
73
|
-
{
|
|
74
|
-
"model": "customers",
|
|
75
|
-
}
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
with pytest.raises(ValueError):
|
|
79
|
-
validate(
|
|
80
|
-
{
|
|
81
|
-
"model": "customers",
|
|
82
|
-
"primary_key": ["customer_id"],
|
|
83
|
-
"columns": "name",
|
|
84
|
-
}
|
|
85
|
-
)
|
tests/test_cli.py
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
from unittest import TestCase
|
|
2
|
-
from unittest.mock import MagicMock, patch
|
|
3
|
-
|
|
4
|
-
from click.testing import CliRunner
|
|
5
|
-
|
|
6
|
-
from recce.cli import run as cli_command_run
|
|
7
|
-
from recce.cli import server as cli_command_server
|
|
8
|
-
from recce.core import RecceContext
|
|
9
|
-
from recce.state import RecceStateLoader
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def test_cmd_version():
|
|
13
|
-
from recce import __version__
|
|
14
|
-
from recce.cli import version
|
|
15
|
-
|
|
16
|
-
runner = CliRunner()
|
|
17
|
-
result = runner.invoke(version, [])
|
|
18
|
-
assert result.exit_code == 0
|
|
19
|
-
assert result.output.replace("\n", "") == __version__
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class TestCommandServer(TestCase):
|
|
23
|
-
def setUp(self):
|
|
24
|
-
self.runner = CliRunner()
|
|
25
|
-
pass
|
|
26
|
-
|
|
27
|
-
@patch.object(RecceContext, "verify_required_artifacts")
|
|
28
|
-
@patch("recce.cli.uvicorn.run")
|
|
29
|
-
def test_cmd_server(self, mock_run, mock_verify_required_artifacts):
|
|
30
|
-
from recce.server import app
|
|
31
|
-
|
|
32
|
-
mock_verify_required_artifacts.return_value = True, None
|
|
33
|
-
self.runner.invoke(cli_command_server, ["--host", "unittest", "--port", 5566, "--single-env"])
|
|
34
|
-
mock_run.assert_called_once_with(app, host="unittest", port=5566, lifespan="on")
|
|
35
|
-
|
|
36
|
-
@patch("recce.cli.uvicorn.run")
|
|
37
|
-
def test_cmd_server_with_cloud_without_password(self, mock_run):
|
|
38
|
-
# Should fail if no password is provided
|
|
39
|
-
result = self.runner.invoke(cli_command_server, ["--cloud"])
|
|
40
|
-
assert result.exit_code == 1
|
|
41
|
-
|
|
42
|
-
@patch("recce.cli.uvicorn.run")
|
|
43
|
-
def test_cmd_server_with_cloud_without_token(self, mock_run):
|
|
44
|
-
# Should fail if no token is provided
|
|
45
|
-
result = self.runner.invoke(cli_command_server, ["--cloud", "--password", "unittest"])
|
|
46
|
-
assert result.exit_code == 1
|
|
47
|
-
|
|
48
|
-
@patch.object(RecceContext, "verify_required_artifacts")
|
|
49
|
-
@patch("recce.util.recce_cloud.get_recce_cloud_onboarding_state")
|
|
50
|
-
@patch("recce.cli.uvicorn.run")
|
|
51
|
-
@patch("recce.cli.RecceStateLoader")
|
|
52
|
-
def test_cmd_server_with_cloud(
|
|
53
|
-
self, mock_state_loader_class, mock_run, mock_get_recce_cloud_onboarding_state, mock_verify_required_artifacts
|
|
54
|
-
):
|
|
55
|
-
mock_state_loader = MagicMock(spec=RecceStateLoader)
|
|
56
|
-
mock_state_loader.verify.return_value = True
|
|
57
|
-
mock_state_loader.review_mode = True
|
|
58
|
-
mock_get_recce_cloud_onboarding_state.return_value = "completed"
|
|
59
|
-
mock_verify_required_artifacts.return_value = True, None
|
|
60
|
-
|
|
61
|
-
mock_state_loader_class.return_value = mock_state_loader
|
|
62
|
-
self.runner.invoke(
|
|
63
|
-
cli_command_server, ["--cloud", "--password", "unittest", "--cloud-token", "unittest", "--single-env"]
|
|
64
|
-
)
|
|
65
|
-
mock_state_loader_class.assert_called_once()
|
|
66
|
-
mock_run.assert_called_once()
|
|
67
|
-
|
|
68
|
-
@patch.object(RecceContext, "verify_required_artifacts")
|
|
69
|
-
@patch("os.path.isdir", side_effect=lambda path: True if path == "existed_folder" else False)
|
|
70
|
-
@patch("recce.cli.uvicorn.run")
|
|
71
|
-
@patch("recce.server.AppState")
|
|
72
|
-
def test_cmd_server_with_single_env(self, mock_app_state, mock_run, mock_isdir, mock_verify_required_artifacts):
|
|
73
|
-
mock_verify_required_artifacts.return_value = True, None
|
|
74
|
-
self.runner.invoke(
|
|
75
|
-
cli_command_server,
|
|
76
|
-
["--single-env", "--target-path", "existed_folder", "--target-base-path", "non_existed_folder"],
|
|
77
|
-
)
|
|
78
|
-
mock_run.assert_called_once()
|
|
79
|
-
|
|
80
|
-
# Onboarding mode should be set to True
|
|
81
|
-
app_state_call_args = mock_app_state.call_args
|
|
82
|
-
app_state_flag = app_state_call_args.kwargs["flag"]
|
|
83
|
-
assert "single_env_onboarding" in app_state_flag
|
|
84
|
-
assert app_state_flag["single_env_onboarding"] is True
|
|
85
|
-
assert "show_relaunch_hint" in app_state_flag
|
|
86
|
-
assert app_state_flag["show_relaunch_hint"] is True
|
|
87
|
-
|
|
88
|
-
# The target_base_path should be set to the same as target_path
|
|
89
|
-
verify_required_artifacts_args = mock_verify_required_artifacts.call_args
|
|
90
|
-
assert (
|
|
91
|
-
verify_required_artifacts_args.kwargs["target_path"]
|
|
92
|
-
== verify_required_artifacts_args.kwargs["target_base_path"]
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
@patch.object(RecceContext, "verify_required_artifacts")
|
|
96
|
-
@patch("os.path.isdir", side_effect=lambda path: True if path == "existed_folder" else False)
|
|
97
|
-
@patch("recce.cli.uvicorn.run")
|
|
98
|
-
@patch("recce.server.AppState")
|
|
99
|
-
def test_cmd_server_with_single_env_but_review_mode_enabled(
|
|
100
|
-
self, mock_app_state, mock_run, mock_isdir, mock_verify_required_artifacts
|
|
101
|
-
):
|
|
102
|
-
mock_verify_required_artifacts.return_value = True, None
|
|
103
|
-
self.runner.invoke(
|
|
104
|
-
cli_command_server,
|
|
105
|
-
[
|
|
106
|
-
"existed_state_file",
|
|
107
|
-
"--review",
|
|
108
|
-
"--single-env",
|
|
109
|
-
"--target-path",
|
|
110
|
-
"existed_folder",
|
|
111
|
-
"--target-base-path",
|
|
112
|
-
"non_existed_folder",
|
|
113
|
-
],
|
|
114
|
-
)
|
|
115
|
-
mock_run.assert_called_once()
|
|
116
|
-
app_state_call_args = mock_app_state.call_args
|
|
117
|
-
app_state_flag = app_state_call_args.kwargs["flag"]
|
|
118
|
-
assert "single_env_onboarding" in app_state_flag
|
|
119
|
-
assert app_state_flag["single_env_onboarding"] is False
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
class TestCommandRun(TestCase):
|
|
123
|
-
def setUp(self):
|
|
124
|
-
self.runner = CliRunner()
|
|
125
|
-
pass
|
|
126
|
-
|
|
127
|
-
@patch.object(RecceContext, "verify_required_artifacts")
|
|
128
|
-
@patch("recce.cli.cli_run")
|
|
129
|
-
def test_cmd_run(self, mock_cli_run, mock_verify_required_artifacts):
|
|
130
|
-
mock_verify_required_artifacts.return_value = True, None
|
|
131
|
-
|
|
132
|
-
self.runner.invoke(cli_command_run, [])
|
|
133
|
-
mock_cli_run.assert_called_once()
|