testery 1.15.2.dev31__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.
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2019 Testery LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,94 @@
1
+ Metadata-Version: 2.4
2
+ Name: testery
3
+ Version: 1.15.2.dev31
4
+ Summary: Testery CLI
5
+ Home-page: https://github.com/testery/testery-cli
6
+ Author: Testery
7
+ Author-email: chris.harbert@testery.io
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: Click
14
+ Requires-Dist: requests>=2.28.0
15
+ Requires-Dist: requests_toolbelt
16
+ Requires-Dist: python-dateutil
17
+ Requires-Dist: python-dotenv
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: license-file
25
+ Dynamic: requires-dist
26
+ Dynamic: summary
27
+
28
+ # Testery CLI
29
+
30
+ To install you must have Python 3 and pip installed, then run:
31
+
32
+ `pip install testery`
33
+
34
+ Upgrade via
35
+
36
+ `pip install testery --upgrade`
37
+
38
+ ## Create Test Run
39
+
40
+ Starts a test run.
41
+
42
+ ```bash
43
+ testery create-test-run --token <yourTesteryApiToken> --project <projectKeyFromTestery> --build-id <uniqueBuildIdOfYourChoice> --environment <environmentToBeTested> --wait-for-results
44
+ ```
45
+
46
+ When set, `--fail-on-failure`, will return an exit code of 1 if there are test failures.
47
+
48
+ ### Output Formats
49
+
50
+ - teamcity
51
+ - pretty
52
+ - json
53
+ - appveyor
54
+ - octopus
55
+
56
+ ## Create Test Environment
57
+
58
+ Creates an environment where tests may be run.
59
+
60
+ ```bash
61
+ testery create-environment --token "<your_Testery_Api_Token>" --key "<key>" --name "<name>" --variable "KEY1=FOO1" --variable "KEY2=FOO2" --variable "secure:KEY3=SECRET" --pipeline-stage "<pipeline_stage_name>"
62
+ ```
63
+
64
+ ## Update Test Environment
65
+
66
+ Updates an environment where tests are run with some new variables or pipeline stage.
67
+
68
+ ```bash
69
+ testery update-environment --token "<your_Testery_Api_Token>" --key "<key>" --name "<name>" --variable "KEY1=FOO1" --variable "KEY2=FOO2" --pipeline-stage "<pipeline_stage_name>"
70
+ ```
71
+
72
+ ## Add environment variables from .env file
73
+
74
+ Takes in a .env file and adds or overwrites variables in target environment.
75
+
76
+ ```bash
77
+ testery add-env-vars-from-file --token "<your_Testery_Api_Token>" --environment-key "<key>" --env-file "<path/to/file/.env>" --overwrite
78
+ ```
79
+
80
+ ## Update Test Stage
81
+
82
+ Updates or creates a pipeline stage where tests are run with some new variables.
83
+
84
+ ```bash
85
+ testery update-pipeline-stage --token "<your_Testery_Api_Token>" --name "<name>" --variable "KEY1=FOO1" --variable "KEY2=FOO2" --create-if-not-exists
86
+ ```
87
+
88
+ ## Add Pipeline Stage variables from .env file
89
+
90
+ Takes in a .env file and adds or overwrites variables in target Pipeline.
91
+
92
+ ```bash
93
+ testery add-stage-vars-from-file --token "<your_Testery_Api_Token>" --name "<name>" --env-file "<path/to/file/.env>" --overwrite
94
+ ```
@@ -0,0 +1,67 @@
1
+ # Testery CLI
2
+
3
+ To install you must have Python 3 and pip installed, then run:
4
+
5
+ `pip install testery`
6
+
7
+ Upgrade via
8
+
9
+ `pip install testery --upgrade`
10
+
11
+ ## Create Test Run
12
+
13
+ Starts a test run.
14
+
15
+ ```bash
16
+ testery create-test-run --token <yourTesteryApiToken> --project <projectKeyFromTestery> --build-id <uniqueBuildIdOfYourChoice> --environment <environmentToBeTested> --wait-for-results
17
+ ```
18
+
19
+ When set, `--fail-on-failure`, will return an exit code of 1 if there are test failures.
20
+
21
+ ### Output Formats
22
+
23
+ - teamcity
24
+ - pretty
25
+ - json
26
+ - appveyor
27
+ - octopus
28
+
29
+ ## Create Test Environment
30
+
31
+ Creates an environment where tests may be run.
32
+
33
+ ```bash
34
+ testery create-environment --token "<your_Testery_Api_Token>" --key "<key>" --name "<name>" --variable "KEY1=FOO1" --variable "KEY2=FOO2" --variable "secure:KEY3=SECRET" --pipeline-stage "<pipeline_stage_name>"
35
+ ```
36
+
37
+ ## Update Test Environment
38
+
39
+ Updates an environment where tests are run with some new variables or pipeline stage.
40
+
41
+ ```bash
42
+ testery update-environment --token "<your_Testery_Api_Token>" --key "<key>" --name "<name>" --variable "KEY1=FOO1" --variable "KEY2=FOO2" --pipeline-stage "<pipeline_stage_name>"
43
+ ```
44
+
45
+ ## Add environment variables from .env file
46
+
47
+ Takes in a .env file and adds or overwrites variables in target environment.
48
+
49
+ ```bash
50
+ testery add-env-vars-from-file --token "<your_Testery_Api_Token>" --environment-key "<key>" --env-file "<path/to/file/.env>" --overwrite
51
+ ```
52
+
53
+ ## Update Test Stage
54
+
55
+ Updates or creates a pipeline stage where tests are run with some new variables.
56
+
57
+ ```bash
58
+ testery update-pipeline-stage --token "<your_Testery_Api_Token>" --name "<name>" --variable "KEY1=FOO1" --variable "KEY2=FOO2" --create-if-not-exists
59
+ ```
60
+
61
+ ## Add Pipeline Stage variables from .env file
62
+
63
+ Takes in a .env file and adds or overwrites variables in target Pipeline.
64
+
65
+ ```bash
66
+ testery add-stage-vars-from-file --token "<your_Testery_Api_Token>" --name "<name>" --env-file "<path/to/file/.env>" --overwrite
67
+ ```
@@ -0,0 +1,277 @@
1
+ import mimetypes
2
+ import os
3
+ import sys
4
+ import time
5
+ from zipfile import ZipFile
6
+
7
+ import click
8
+ import dateutil.parser
9
+ import requests
10
+ # we have to do this right now because of how our S3 buckets are named. This should be removed once we've fixed that
11
+ import urllib3
12
+ from dotenv import dotenv_values
13
+ from requests_toolbelt.multipart.encoder import MultipartEncoder
14
+
15
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
16
+
17
+ headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
18
+
19
+
20
+ class CommonCommands(click.core.Command):
21
+ def __init__(self, *args, **kwargs):
22
+ super().__init__(*args, **kwargs)
23
+ self.params.insert(0, click.Option(('--token',), required=True, help='Your Testery API token.'))
24
+ self.params.insert(0, click.Option(('--testery-dev',), is_flag=True, default=False, hidden=True))
25
+
26
+
27
+ def get_api_url(is_dev):
28
+ if is_dev:
29
+ return 'https://api.dev.testery.io/api'
30
+ return 'https://api.testery.io/api'
31
+
32
+
33
+ def report_test_run(test_run, output):
34
+ if output == "teamcity":
35
+ report_teamcity_test_run(test_run)
36
+ elif output == "json":
37
+ print(test_run)
38
+ else:
39
+ report_pretty_test_run(test_run)
40
+
41
+
42
+ def report_pretty_test_run(test_run):
43
+ if test_run['status'] == 'SUBMITTED':
44
+ print("Waiting for test run to start")
45
+ elif test_run['totalCount'] == 0 and test_run['status'] == 'RUNNING':
46
+ print("Getting list of tests to run")
47
+ elif test_run['totalCount'] == 0:
48
+ print("No tests run")
49
+ elif test_run['ignoredCount'] == 0:
50
+ if test_run['status'] == 'RUNNING':
51
+ text = "Running"
52
+ else:
53
+ text = "Completed"
54
+ print("%s: %s of %s pass with %s fail" % (text, test_run['passCount'], test_run['totalCount'], test_run['failCount']))
55
+ else:
56
+ if test_run['status'] == 'RUNNING':
57
+ text = "Running"
58
+ else:
59
+ text = "Completed"
60
+ print("%s: %s of %s pass with %s fail and %s ignored" % (text, test_run['passCount'], test_run['totalCount'], test_run['failCount'], test_run['ignoredCount']))
61
+
62
+
63
+ def report_teamcity_test_run(test_run):
64
+ if test_run['status'] == 'FAIL':
65
+ print("##teamcity[buildProblem description='%s: %s passing, %s failing out of %s total']" % (
66
+ test_run['status'], test_run['passCount'], test_run['failCount'], test_run['totalCount']))
67
+ else:
68
+ print("##teamcity[buildStatus text='%s: %s passing, %s failing out of %s total']" % (
69
+ test_run['status'], test_run['passCount'], test_run['failCount'], test_run['totalCount']))
70
+
71
+
72
+ def api_wait_test_run(api_url, token, test_run_id, output, fail_on_failure):
73
+ headers['Authorization'] = "Bearer " + token
74
+
75
+ test_run = requests.get(api_url + '/test-runs/' + str(test_run_id), headers=headers).json()
76
+
77
+ report_test_run(test_run, output)
78
+
79
+ while test_run['status'] not in ['PASS', 'FAIL', 'CANCELED']:
80
+ time.sleep(15)
81
+ test_run = requests.get(api_url + '/test-runs/' + str(test_run_id), headers=headers).json()
82
+ report_test_run(test_run, output)
83
+
84
+ if (test_run['status'] == 'FAIL' or test_run['status'] == 'CANCELED') and fail_on_failure:
85
+ print('Test run had failures')
86
+ sys.exit(1)
87
+
88
+
89
+ def api_wait_deploy(api_url, token, deploy_id, output, fail_on_failure):
90
+ headers['Authorization'] = "Bearer " + token
91
+
92
+ test_runs = requests.get(api_url + '/test-runs/by-deploy/' + str(deploy_id), headers=headers).json()
93
+
94
+ for test_run in test_runs:
95
+ click.echo("Waiting for test run: %s" % test_run['id'])
96
+ api_wait_test_run(api_url, token, test_run['id'], output, fail_on_failure)
97
+
98
+ click.echo("All test runs for deployment #%s are complete." % deploy_id)
99
+
100
+
101
+ def add_vars_from_file(file: str, body: dict, overwrite: bool = False):
102
+ new_vars = {}
103
+ json = []
104
+ for var in body["variables"]:
105
+ new_vars[var['key']] = var
106
+ config = dotenv_values(file)
107
+ for var in config:
108
+ if var in new_vars:
109
+ if overwrite:
110
+ new_vars[var] = {'key': var, 'value': config[var], 'encrypted': False, 'file': False}
111
+ else:
112
+ new_vars[var] = {'key': var, 'value': config[var], 'encrypted': False, 'file': False}
113
+ for value in new_vars.values():
114
+ json.append(value)
115
+ body["variables"] = json
116
+
117
+
118
+ def find_environment_by_key(api_url, token, environment_key):
119
+ environments_response = requests.get(api_url + '/environments', headers=headers)
120
+
121
+ environments = environments_response.json()
122
+
123
+ for environment in environments:
124
+ if environment['key'] == environment_key:
125
+ return environment
126
+
127
+ raise Exception("Environment with key not found: " + environment_key)
128
+
129
+
130
+ def find_test_plan_by_key(api_url, token, test_plan_key):
131
+ test_plans_response = requests.get(api_url + '/test-plans', headers=headers)
132
+
133
+ testplans = test_plans_response.json()
134
+
135
+ for test_plan in testplans:
136
+ if test_plan['key'] == test_plan_key:
137
+ return test_plan
138
+
139
+ raise Exception("Test Plan with key not found: " + test_plan_key)
140
+
141
+
142
+ def find_pipeline_stage_by_name(api_url, pipeline_stage_name):
143
+ stages_response = requests.get(api_url + '/pipeline-stages', headers=headers)
144
+ stages_response.raise_for_status()
145
+
146
+ stages = stages_response.json()
147
+ lower_name = pipeline_stage_name.lower()
148
+ for stage in stages:
149
+ if stage['name'].lower() == lower_name:
150
+ return stage
151
+
152
+ stage_names = map(lambda s: s['name'], stages)
153
+ message = "Could not find pipeline stage with name '" + pipeline_stage_name + "'. Known names: " + ', '.join(stage_names)
154
+ raise Exception(message)
155
+
156
+
157
+ def find_project_by_key(api_url, token, project_key):
158
+ response = requests.get(api_url + '/projects', headers=headers)
159
+
160
+ projects = response.json()
161
+
162
+ for project in projects:
163
+ if project['key'] == project_key:
164
+ return project
165
+
166
+ raise Exception("Project with key not found: " + project_key)
167
+
168
+
169
+ def find_test_suite_by_name(api_url, suite_name, project_id):
170
+ test_suites_response = requests.get(api_url + f'/projects/{project_id}/test-suites', headers=headers)
171
+
172
+ test_suites = test_suites_response.json()
173
+ lower_name = suite_name.lower()
174
+
175
+ for suite in test_suites:
176
+ if suite['name'].lower() == lower_name:
177
+ return suite
178
+
179
+ test_suite_names = map(lambda s: s['name'], test_suites)
180
+ message = "Could not find test suite with name '" + suite_name + "'. Known names: " + ', '.join(test_suite_names)
181
+ raise Exception(message)
182
+
183
+
184
+ def handle_variables(variables, request):
185
+ if variables:
186
+ vars = []
187
+ for var in variables:
188
+ (vkey, vval) = var.split("=")
189
+
190
+ if vkey.startswith("secure:"):
191
+ vkey = vkey.replace("secure:", "")
192
+ encrypted = True
193
+ else:
194
+ encrypted = False
195
+
196
+ v = {"key": vkey, "value": vval, "encrypted": encrypted}
197
+ vars.append(v)
198
+ request["variables"] = vars
199
+
200
+
201
+ def create_zip_file(path, temp_dir):
202
+ zip_file = ZipFile(os.path.join(temp_dir, str(time.time()) + '.zip'), 'w')
203
+ len_path = len(path)
204
+ with zip_file as zip_file:
205
+ exclude = {'.git', 'node_modules'}
206
+ for root, dirs, files in os.walk(path):
207
+ dirs[:] = [d for d in dirs if d not in exclude]
208
+ for file in files:
209
+ file_path = os.path.join(root, file)
210
+ zip_file.write(file_path, file_path[len_path:])
211
+ return zip_file
212
+
213
+
214
+ def upload_build_artifact_dir(base_api_url, file_path, dir_path):
215
+ for file in os.listdir(file_path):
216
+ new_file_path = os.path.join(file_path, file)
217
+ if os.path.isdir(new_file_path):
218
+ dir_name = os.path.basename(new_file_path)
219
+ upload_build_artifact_dir(
220
+ base_api_url, new_file_path, dir_path + dir_name + '/')
221
+ else:
222
+ upload_build_artifact_file(base_api_url, new_file_path, dir_path)
223
+
224
+
225
+ def upload_build_artifact_file(base_api_url, file_path, dir_path):
226
+ file = dir_path + os.path.basename(file_path)
227
+
228
+ upload_result = requests.get(base_api_url + file, headers=headers)
229
+
230
+ upload_url = upload_result.text
231
+
232
+ if upload_result.status_code != 200 or upload_url == "invalid request":
233
+ raise Exception("Could not upload artifacts. Make sure you specified the correct project key.")
234
+
235
+ result = upload_file(
236
+ upload_url, {'Accept': 'application/json'}, file_path, False)
237
+
238
+ if result.status_code != 200:
239
+ raise Exception("Got status code " + str(result.status_code) +
240
+ " when trying to upload file with path " + file_path)
241
+
242
+
243
+ def upload_file(url, headers, file_path, for_add_file):
244
+ file_name = os.path.basename(file_path)
245
+ mime_type = mimetypes.guess_type(file_path)[0]
246
+
247
+ if mime_type is None:
248
+ mime_type = "text/plain"
249
+
250
+ if for_add_file:
251
+ data = MultipartEncoder(
252
+ fields={'file': (file_name, open(file_path, 'rb'), mime_type)})
253
+ headers['Content-Type'] = data.content_type
254
+ return requests.post(url, headers=headers, data=data)
255
+ else:
256
+ headers['Content-Type'] = mime_type
257
+ data = open(file_path, 'rb')
258
+ return requests.put(url, data=data, verify=False)
259
+
260
+
261
+ def wait_for_maintenance_window():
262
+ status = requests.get('http://status.testery.io/api/v2/scheduled-maintenances/active.json', headers=headers)
263
+ status.raise_for_status()
264
+ scheduled_maintenances = status.json().get('scheduled_maintenances')
265
+
266
+ if len(scheduled_maintenances) > 0:
267
+ scheduled_until = dateutil.parser.parse(scheduled_maintenances[0]['scheduled_until'])
268
+ print("Testery is undergoing scheduled maintenance which is scheduled to end at %s UTC. To make sure you have a stable test run, we are pausing your build. Your build will resume automatically as soon as the system is confirmed to be fully operational. Learn more about the event at http://status.testery.io/\n" % scheduled_until)
269
+
270
+ while len(scheduled_maintenances) > 0:
271
+ print(".")
272
+ time.sleep(300)
273
+ status = requests.get('http://status.testery.io/api/v2/scheduled-maintenances/active.json', headers=headers)
274
+ status.raise_for_status()
275
+ scheduled_maintenances = status.json().get('scheduled_maintenances')
276
+
277
+ print("Testery's scheduled maintenance is now complete. We'd like to thank you for your patience and for being such an awesome customer. Happy testing and good luck with this test run!")
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,27 @@
1
+ import setuptools
2
+
3
+ with open("README.md", "r") as fh:
4
+ long_description = fh.read()
5
+
6
+ setuptools.setup(
7
+ name='testery',
8
+ version='1.15.2-dev31',
9
+ install_requires=['Click', 'requests>=2.28.0', 'requests_toolbelt', 'python-dateutil', 'python-dotenv'],
10
+ py_modules=['testery', 'helpers'],
11
+ entry_points='''
12
+ [console_scripts]
13
+ testery=testery:cli
14
+ ''',
15
+ author="Testery",
16
+ author_email="chris.harbert@testery.io",
17
+ description="Testery CLI",
18
+ long_description=long_description,
19
+ long_description_content_type="text/markdown",
20
+ url="https://github.com/testery/testery-cli",
21
+ packages=setuptools.find_packages(),
22
+ classifiers=[
23
+ "Programming Language :: Python :: 3",
24
+ "License :: OSI Approved :: MIT License",
25
+ "Operating System :: OS Independent",
26
+ ],
27
+ )
@@ -0,0 +1,94 @@
1
+ Metadata-Version: 2.4
2
+ Name: testery
3
+ Version: 1.15.2.dev31
4
+ Summary: Testery CLI
5
+ Home-page: https://github.com/testery/testery-cli
6
+ Author: Testery
7
+ Author-email: chris.harbert@testery.io
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: Click
14
+ Requires-Dist: requests>=2.28.0
15
+ Requires-Dist: requests_toolbelt
16
+ Requires-Dist: python-dateutil
17
+ Requires-Dist: python-dotenv
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: home-page
24
+ Dynamic: license-file
25
+ Dynamic: requires-dist
26
+ Dynamic: summary
27
+
28
+ # Testery CLI
29
+
30
+ To install you must have Python 3 and pip installed, then run:
31
+
32
+ `pip install testery`
33
+
34
+ Upgrade via
35
+
36
+ `pip install testery --upgrade`
37
+
38
+ ## Create Test Run
39
+
40
+ Starts a test run.
41
+
42
+ ```bash
43
+ testery create-test-run --token <yourTesteryApiToken> --project <projectKeyFromTestery> --build-id <uniqueBuildIdOfYourChoice> --environment <environmentToBeTested> --wait-for-results
44
+ ```
45
+
46
+ When set, `--fail-on-failure`, will return an exit code of 1 if there are test failures.
47
+
48
+ ### Output Formats
49
+
50
+ - teamcity
51
+ - pretty
52
+ - json
53
+ - appveyor
54
+ - octopus
55
+
56
+ ## Create Test Environment
57
+
58
+ Creates an environment where tests may be run.
59
+
60
+ ```bash
61
+ testery create-environment --token "<your_Testery_Api_Token>" --key "<key>" --name "<name>" --variable "KEY1=FOO1" --variable "KEY2=FOO2" --variable "secure:KEY3=SECRET" --pipeline-stage "<pipeline_stage_name>"
62
+ ```
63
+
64
+ ## Update Test Environment
65
+
66
+ Updates an environment where tests are run with some new variables or pipeline stage.
67
+
68
+ ```bash
69
+ testery update-environment --token "<your_Testery_Api_Token>" --key "<key>" --name "<name>" --variable "KEY1=FOO1" --variable "KEY2=FOO2" --pipeline-stage "<pipeline_stage_name>"
70
+ ```
71
+
72
+ ## Add environment variables from .env file
73
+
74
+ Takes in a .env file and adds or overwrites variables in target environment.
75
+
76
+ ```bash
77
+ testery add-env-vars-from-file --token "<your_Testery_Api_Token>" --environment-key "<key>" --env-file "<path/to/file/.env>" --overwrite
78
+ ```
79
+
80
+ ## Update Test Stage
81
+
82
+ Updates or creates a pipeline stage where tests are run with some new variables.
83
+
84
+ ```bash
85
+ testery update-pipeline-stage --token "<your_Testery_Api_Token>" --name "<name>" --variable "KEY1=FOO1" --variable "KEY2=FOO2" --create-if-not-exists
86
+ ```
87
+
88
+ ## Add Pipeline Stage variables from .env file
89
+
90
+ Takes in a .env file and adds or overwrites variables in target Pipeline.
91
+
92
+ ```bash
93
+ testery add-stage-vars-from-file --token "<your_Testery_Api_Token>" --name "<name>" --env-file "<path/to/file/.env>" --overwrite
94
+ ```
@@ -0,0 +1,15 @@
1
+ LICENSE
2
+ README.md
3
+ helpers.py
4
+ setup.py
5
+ testery.py
6
+ testery.egg-info/PKG-INFO
7
+ testery.egg-info/SOURCES.txt
8
+ testery.egg-info/dependency_links.txt
9
+ testery.egg-info/entry_points.txt
10
+ testery.egg-info/requires.txt
11
+ testery.egg-info/top_level.txt
12
+ tests/__init__.py
13
+ tests/conftest.py
14
+ tests/test_integration.py
15
+ tests/test_unit.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ testery = testery:cli
@@ -0,0 +1,5 @@
1
+ Click
2
+ requests>=2.28.0
3
+ requests_toolbelt
4
+ python-dateutil
5
+ python-dotenv
@@ -0,0 +1,3 @@
1
+ helpers
2
+ testery
3
+ tests