testrail-api-module 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.
- testrail_api_module-0.1.0/LICENSE +21 -0
- testrail_api_module-0.1.0/PKG-INFO +10 -0
- testrail_api_module-0.1.0/README.md +9 -0
- testrail_api_module-0.1.0/pyproject.toml +21 -0
- testrail_api_module-0.1.0/setup.cfg +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/__init__.py +57 -0
- testrail_api_module-0.1.0/src/testrail_api_module/_common.py +115 -0
- testrail_api_module-0.1.0/src/testrail_api_module/attachments.py +187 -0
- testrail_api_module-0.1.0/src/testrail_api_module/bdd.py +34 -0
- testrail_api_module-0.1.0/src/testrail_api_module/case_fields.py +42 -0
- testrail_api_module-0.1.0/src/testrail_api_module/case_types.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/cases.py +229 -0
- testrail_api_module-0.1.0/src/testrail_api_module/configurations.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/datasets.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/groups.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/milestones.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/plans.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/priorities.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/projects.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/reports.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/result_fields.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/results.py +91 -0
- testrail_api_module-0.1.0/src/testrail_api_module/roles.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/runs.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/sections.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/shared_steps.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/statuses.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/suites.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/templates.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/tests.py +41 -0
- testrail_api_module-0.1.0/src/testrail_api_module/users.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module/variables.py +4 -0
- testrail_api_module-0.1.0/src/testrail_api_module.egg-info/PKG-INFO +10 -0
- testrail_api_module-0.1.0/src/testrail_api_module.egg-info/SOURCES.txt +35 -0
- testrail_api_module-0.1.0/src/testrail_api_module.egg-info/dependency_links.txt +1 -0
- testrail_api_module-0.1.0/src/testrail_api_module.egg-info/requires.txt +1 -0
- testrail_api_module-0.1.0/src/testrail_api_module.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Matt Troutman
|
|
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,10 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: testrail_api_module
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A simple wrapper for the TestRail API
|
|
5
|
+
Author: Christian Thompson
|
|
6
|
+
Author-email: Matt Troutman <github@trtmn.com>
|
|
7
|
+
Project-URL: Homepage, https://github.com/trtmn/testrail_api_module
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: requests
|
|
10
|
+
Dynamic: license-file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "testrail_api_module"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A simple wrapper for the TestRail API"
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Matt Troutman", email = "github@trtmn.com" },
|
|
11
|
+
{ name = "Christian Thompson"}
|
|
12
|
+
]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"requests",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[tool.setuptools.packages.find]
|
|
18
|
+
where = ["src"]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://github.com/trtmn/testrail_api_module"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# src/testrail_api_module/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
This package provides functionalities to interact with the TestRail API, including managing attachments, cases, tests, and results.
|
|
4
|
+
|
|
5
|
+
Attributes:
|
|
6
|
+
__version__ (str): The version of the package.
|
|
7
|
+
__author__ (str): The authors of the package.
|
|
8
|
+
__all__ (list): A list of modules to be imported when `from testrail_api_module import *` is used.
|
|
9
|
+
"""
|
|
10
|
+
import os
|
|
11
|
+
__version__ = '0.1.0'
|
|
12
|
+
__author__ = 'Matt Troutman / Christian Thompson'
|
|
13
|
+
package_version = __version__
|
|
14
|
+
"""The version of the package, used for compatibility checks and logging."""
|
|
15
|
+
|
|
16
|
+
authors = __author__
|
|
17
|
+
"""authors of the package, used for documentation and attribution."""
|
|
18
|
+
|
|
19
|
+
# Import all modules in the package
|
|
20
|
+
__all__ = [
|
|
21
|
+
'_common',
|
|
22
|
+
'attachments',
|
|
23
|
+
'bdd',
|
|
24
|
+
'case_fields',
|
|
25
|
+
'case_types',
|
|
26
|
+
'cases',
|
|
27
|
+
'configurations',
|
|
28
|
+
'datasets',
|
|
29
|
+
'groups',
|
|
30
|
+
'milestones',
|
|
31
|
+
'plans',
|
|
32
|
+
'priorities',
|
|
33
|
+
'projects',
|
|
34
|
+
'reports',
|
|
35
|
+
'result_fields',
|
|
36
|
+
'results',
|
|
37
|
+
'roles',
|
|
38
|
+
'runs',
|
|
39
|
+
'sections',
|
|
40
|
+
'shared_steps',
|
|
41
|
+
'statuses',
|
|
42
|
+
'suites',
|
|
43
|
+
'templates',
|
|
44
|
+
'tests',
|
|
45
|
+
'users',
|
|
46
|
+
'variables'
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
def __import_all_modules__():
|
|
50
|
+
for _x in __all__:
|
|
51
|
+
_local_name = f".{_x}"
|
|
52
|
+
exec(f"from {_local_name} import *", globals())
|
|
53
|
+
|
|
54
|
+
__import_all_modules__()
|
|
55
|
+
del __import_all_modules__
|
|
56
|
+
|
|
57
|
+
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""
|
|
2
|
+
`_common.py` serves as a foundational module for the TestRail API package, providing a base class for API requests and a function to set API credentials.
|
|
3
|
+
"""
|
|
4
|
+
import requests
|
|
5
|
+
import json
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
def set_testrail_api_credentials(baseurl=None, username=None, password=None):
|
|
11
|
+
"""
|
|
12
|
+
Set the TestRail API credentials as environment variables.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
baseurl (str): The base URL for the TestRail API.
|
|
16
|
+
username (str): The username for TestRail API authentication.
|
|
17
|
+
password (str): The password for TestRail API authentication.
|
|
18
|
+
"""
|
|
19
|
+
if baseurl is not None:
|
|
20
|
+
os.environ["TESTRAIL_API_BASEURL"] = baseurl
|
|
21
|
+
if username is not None:
|
|
22
|
+
os.environ["TESTRAIL_API_USERNAME"] = username
|
|
23
|
+
if password is not None:
|
|
24
|
+
os.environ["TESTRAIL_API_PASSWORD"] = password
|
|
25
|
+
|
|
26
|
+
def get_testrail_api_credentials():
|
|
27
|
+
"""
|
|
28
|
+
Get the TestRail API credentials from environment variables.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
tuple: A tuple containing the baseurl, username, and password.
|
|
32
|
+
|
|
33
|
+
Raises:
|
|
34
|
+
ValueError: If any of the required credentials are not set.
|
|
35
|
+
"""
|
|
36
|
+
baseurl = os.getenv("TESTRAIL_API_BASEURL")
|
|
37
|
+
username = os.getenv("TESTRAIL_API_USERNAME")
|
|
38
|
+
password = os.getenv("TESTRAIL_API_PASSWORD")
|
|
39
|
+
|
|
40
|
+
if baseurl is None:
|
|
41
|
+
raise ValueError("The base URL for the TestRail API is required. Set it as an environment variable or pass it as an argument.")
|
|
42
|
+
if username is None:
|
|
43
|
+
raise ValueError("The username for TestRail API authentication is required. Set it as an environment variable or pass it as an argument.")
|
|
44
|
+
if password is None:
|
|
45
|
+
raise ValueError("The password for TestRail API authentication is required. Set it as an environment variable or pass it as an argument.")
|
|
46
|
+
|
|
47
|
+
return baseurl, username, password
|
|
48
|
+
|
|
49
|
+
class ApiConstructor:
|
|
50
|
+
"""
|
|
51
|
+
A class to construct and make API requests to TestRail.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(self) -> object:
|
|
55
|
+
"""
|
|
56
|
+
Initializes the ApiConstructor with default values for run_id, case_id, project_id,
|
|
57
|
+
baseurl, username, and password.
|
|
58
|
+
"""
|
|
59
|
+
self.run_id = None # Actual run id in demo project
|
|
60
|
+
"""The run ID for the TestRail run. This is required."""
|
|
61
|
+
|
|
62
|
+
self.case_id = None # Actual case id in demo project
|
|
63
|
+
"""The case ID for the TestRail case. This is required."""
|
|
64
|
+
|
|
65
|
+
self.project_id = None
|
|
66
|
+
"""The project ID for the TestRail project. This is required."""
|
|
67
|
+
|
|
68
|
+
self.baseurl = get_testrail_api_credentials()[0] #Required!
|
|
69
|
+
"""The base URL for the TestRail API (e.g., "https://your_testrail_instance.testrail.io"). This is required.
|
|
70
|
+
Can be set in the constructor or as an environment variable.
|
|
71
|
+
use testrail_api_module._common.set_testrail_api_credentials()"""
|
|
72
|
+
|
|
73
|
+
self.username = get_testrail_api_credentials()[1] #Required!
|
|
74
|
+
"""The username for TestRail API authentication. This is required.
|
|
75
|
+
Can be set in the constructor or as an environment variable.
|
|
76
|
+
use testrail_api_module._common.set_testrail_api_credentials()"""
|
|
77
|
+
|
|
78
|
+
self.password = get_testrail_api_credentials()[2] #Required!
|
|
79
|
+
"""The password for TestRail API authentication. This is required.
|
|
80
|
+
Can be set in the constructor or as an environment variable.
|
|
81
|
+
use testrail_api_module._common.set_testrail_api_credentials()"""
|
|
82
|
+
|
|
83
|
+
def api_request(self, method, endpoint, data=None):
|
|
84
|
+
"""
|
|
85
|
+
Make an API request to TestRail.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
method (str): The HTTP method to use for the request (e.g., 'GET', 'POST').
|
|
89
|
+
endpoint (str): The API endpoint to send the request to.
|
|
90
|
+
data (dict, optional): The data to send with the request, if any.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
dict: The JSON response from the API if the request is successful.
|
|
94
|
+
None: If the request fails.
|
|
95
|
+
"""
|
|
96
|
+
# Confirm that all 3 required variables are set
|
|
97
|
+
if not self.baseurl:
|
|
98
|
+
raise ValueError("The base URL for the TestRail API is required. See documentation for more info")
|
|
99
|
+
if not self.username:
|
|
100
|
+
raise ValueError("The username for TestRail API authentication is required. See documentation for more info")
|
|
101
|
+
if not self.password:
|
|
102
|
+
raise ValueError("The password for TestRail API authentication is required. See documentation for more info")
|
|
103
|
+
|
|
104
|
+
url = f"{self.baseurl}/index.php?/api/v2/{endpoint}"
|
|
105
|
+
headers = {"Content-Type": "application/json"}
|
|
106
|
+
response = requests.request(method, url, headers=headers, data=json.dumps(data), auth=(self.username, self.password))
|
|
107
|
+
if response.status_code == 200:
|
|
108
|
+
return response.json()
|
|
109
|
+
else:
|
|
110
|
+
print(f"Failed to {method} {endpoint}. Response:", response.text)
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
if __name__ == '__main__':
|
|
114
|
+
set_testrail_api_credentials(baseurl="https://your_testrail_instance.testrail.io", username="your_username", password="your_password")
|
|
115
|
+
print(get_testrail_api_credentials())
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
from . import _common
|
|
2
|
+
_api = _common.ApiConstructor()
|
|
3
|
+
"""
|
|
4
|
+
This module provides functionalities to interact with attachments in TestRail.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def add_attachment_to_case(case_id, file_path):
|
|
9
|
+
"""
|
|
10
|
+
Add an attachment to a specific test case.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
case_id (str): The ID of the test case.
|
|
14
|
+
file_path (str): The path to the file to be attached.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
dict: The response from the API.
|
|
18
|
+
"""
|
|
19
|
+
files = {'attachment': open(file_path, 'rb')}
|
|
20
|
+
headers = {'Content-Type': 'multipart/form-data'}
|
|
21
|
+
response = _api.api_request('POST', f'add_attachment_to_case/{case_id}', files=files, headers=headers)
|
|
22
|
+
return response
|
|
23
|
+
|
|
24
|
+
def add_attachment_to_plan(plan_id, file_path):
|
|
25
|
+
"""
|
|
26
|
+
Add an attachment to a specific test plan.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
plan_id (str): The ID of the test plan.
|
|
30
|
+
file_path (str): The path to the file to be attached.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
dict: The response from the API.
|
|
34
|
+
"""
|
|
35
|
+
files = {'attachment': open(file_path, 'rb')}
|
|
36
|
+
headers = {'Content-Type': 'multipart/form-data'}
|
|
37
|
+
response = _api.api_request('POST', f'add_attachment_to_plan/{plan_id}', files=files, headers=headers)
|
|
38
|
+
return response
|
|
39
|
+
|
|
40
|
+
def add_attachment_to_plan_entry(plan_id, entry_id, file_path):
|
|
41
|
+
"""
|
|
42
|
+
Add an attachment to a specific test plan entry.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
plan_id (str): The ID of the test plan.
|
|
46
|
+
entry_id (str): The ID of the test plan entry.
|
|
47
|
+
file_path (str): The path to the file to be attached.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
dict: The response from the API.
|
|
51
|
+
"""
|
|
52
|
+
files = {'attachment': open(file_path, 'rb')}
|
|
53
|
+
headers = {'Content-Type': 'multipart/form-data'}
|
|
54
|
+
response = _api.api_request('POST', f'add_attachment_to_plan_entry/{plan_id}/{entry_id}', files=files, headers=headers)
|
|
55
|
+
return response
|
|
56
|
+
|
|
57
|
+
def add_attachment_to_result(result_id, file_path):
|
|
58
|
+
"""
|
|
59
|
+
Add an attachment to a specific test result.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
result_id (str): The ID of the test result.
|
|
63
|
+
file_path (str): The path to the file to be attached.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
dict: The response from the API.
|
|
67
|
+
"""
|
|
68
|
+
files = {'attachment': open(file_path, 'rb')}
|
|
69
|
+
headers = {'Content-Type': 'multipart/form-data'}
|
|
70
|
+
response = _api.api_request('POST', f'add_attachment_to_result/{result_id}', files=files, headers=headers)
|
|
71
|
+
return response
|
|
72
|
+
|
|
73
|
+
def add_attachment_to_run(run_id, file_path):
|
|
74
|
+
"""
|
|
75
|
+
Add an attachment to a specific test run.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
run_id (str): The ID of the test run.
|
|
79
|
+
file_path (str): The path to the file to be attached.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
dict: The response from the API.
|
|
83
|
+
"""
|
|
84
|
+
files = {'attachment': open(file_path, 'rb')}
|
|
85
|
+
headers = {'Content-Type': 'multipart/form-data'}
|
|
86
|
+
response = _api.api_request('POST', f'add_attachment_to_run/{run_id}', files=files, headers=headers)
|
|
87
|
+
return response
|
|
88
|
+
|
|
89
|
+
def get_attachments_for_case(case_id, limit=250, offset=0):
|
|
90
|
+
"""
|
|
91
|
+
Get all attachments for a specific test case.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
case_id (str): The ID of the test case.
|
|
95
|
+
limit (int, optional): The maximum number of attachments to return (default is 250).
|
|
96
|
+
offset (int, optional): The number of attachments to skip before starting to collect the result set (default is 0).
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
dict: The response from the API.
|
|
100
|
+
"""
|
|
101
|
+
response = _api.api_request('GET', f'get_attachments_for_case/{case_id}&limit={limit}&offset={offset}')
|
|
102
|
+
return response
|
|
103
|
+
|
|
104
|
+
def get_attachments_for_plan(plan_id, limit=250, offset=0):
|
|
105
|
+
"""
|
|
106
|
+
Get all attachments for a specific test plan.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
plan_id (str): The ID of the test plan.
|
|
110
|
+
limit (int, optional): The maximum number of attachments to return (default is 250).
|
|
111
|
+
offset (int, optional): The number of attachments to skip before starting to collect the result set (default is 0).
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
dict: The response from the API.
|
|
115
|
+
"""
|
|
116
|
+
response = _api.api_request('GET', f'get_attachments_for_plan/{plan_id}&limit={limit}&offset={offset}')
|
|
117
|
+
return response
|
|
118
|
+
|
|
119
|
+
def get_attachments_for_plan_entry(plan_id, entry_id, limit=250, offset=0):
|
|
120
|
+
"""
|
|
121
|
+
Get all attachments for a specific test plan entry.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
plan_id (str): The ID of the test plan.
|
|
125
|
+
entry_id (str): The ID of the test plan entry.
|
|
126
|
+
limit (int, optional): The maximum number of attachments to return (default is 250).
|
|
127
|
+
offset (int, optional): The number of attachments to skip before starting to collect the result set (default is 0).
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
dict: The response from the API.
|
|
131
|
+
"""
|
|
132
|
+
response = _api.api_request('GET', f'get_attachments_for_plan_entry/{plan_id}/{entry_id}&limit={limit}&offset={offset}')
|
|
133
|
+
return response
|
|
134
|
+
|
|
135
|
+
def get_attachments_for_run(run_id, limit=250, offset=0):
|
|
136
|
+
"""
|
|
137
|
+
Get all attachments for a specific test run.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
run_id (str): The ID of the test run.
|
|
141
|
+
limit (int, optional): The maximum number of attachments to return (default is 250).
|
|
142
|
+
offset (int, optional): The number of attachments to skip before starting to collect the result set (default is 0).
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
dict: The response from the API.
|
|
146
|
+
"""
|
|
147
|
+
response = _api.api_request('GET', f'get_attachments_for_run/{run_id}?limit={limit}&offset={offset}')
|
|
148
|
+
return response
|
|
149
|
+
|
|
150
|
+
def get_attachments_for_test(test_id):
|
|
151
|
+
"""
|
|
152
|
+
Get all attachments for a specific test.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
test_id (str): The ID of the test.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
dict: The response from the API.
|
|
159
|
+
"""
|
|
160
|
+
response = _api.api_request('GET', f'get_attachments_for_test/{test_id}')
|
|
161
|
+
return response
|
|
162
|
+
|
|
163
|
+
def get_attachment(attachment_id):
|
|
164
|
+
"""
|
|
165
|
+
Get details of a specific attachment.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
attachment_id (str): The ID of the attachment.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
dict: The response from the API.
|
|
172
|
+
"""
|
|
173
|
+
response = _api.api_request('GET', f'get_attachment/{attachment_id}')
|
|
174
|
+
return response
|
|
175
|
+
|
|
176
|
+
def delete_attachment(attachment_id):
|
|
177
|
+
"""
|
|
178
|
+
Delete a specific attachment.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
attachment_id (str): The ID of the attachment.
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
dict: The response from the API.
|
|
185
|
+
"""
|
|
186
|
+
response = _api.api_request('POST', f'delete_attachment/{attachment_id}')
|
|
187
|
+
return response
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from . import _common
|
|
2
|
+
_api = _common.ApiConstructor()
|
|
3
|
+
"""
|
|
4
|
+
This module provides functionalities to interact with BDD scenarios in TestRail.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
def get_bdd(case_id):
|
|
8
|
+
"""
|
|
9
|
+
Export a BDD scenario from a test case as a .feature file.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
case_id (int): The ID of the test case.
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
dict: The response from the API.
|
|
16
|
+
"""
|
|
17
|
+
return _api.api_request('GET', f'get_bdd/{case_id}')
|
|
18
|
+
|
|
19
|
+
def add_bdd(section_id, feature_file):
|
|
20
|
+
"""
|
|
21
|
+
Import/upload a BDD scenario from a test case as a .feature file.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
section_id (int): The ID of the section.
|
|
25
|
+
feature_file (str): The path to the .feature file.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
dict: The response from the API.
|
|
29
|
+
"""
|
|
30
|
+
with open(feature_file, 'r') as file:
|
|
31
|
+
data = {
|
|
32
|
+
"file": file.read()
|
|
33
|
+
}
|
|
34
|
+
return _api.api_request('POST', f'add_bdd/{section_id}', data)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# src/testrail_api_module/case_fields.py
|
|
2
|
+
"""
|
|
3
|
+
This module provides functionalities to interact with test case fields in TestRail.
|
|
4
|
+
"""
|
|
5
|
+
from . import _common
|
|
6
|
+
_api = _common.ApiConstructor()
|
|
7
|
+
|
|
8
|
+
def get_case_fields():
|
|
9
|
+
"""
|
|
10
|
+
Get all available test case fields.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
list: A list of dictionaries containing the details of each test case field.
|
|
14
|
+
"""
|
|
15
|
+
return _api.api_request('GET', 'get_case_fields')
|
|
16
|
+
|
|
17
|
+
def add_case_field(field_type, name, label, description=None, include_all=False, template_ids=None, configs=None):
|
|
18
|
+
"""
|
|
19
|
+
Create a new test case custom field.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
field_type (str): The type identifier for the new custom field.
|
|
23
|
+
name (str): The name for the new custom field.
|
|
24
|
+
label (str): The label for the new custom field.
|
|
25
|
+
description (str, optional): The description for the new custom field.
|
|
26
|
+
include_all (bool, optional): Flag to include the new custom field for all templates.
|
|
27
|
+
template_ids (list, optional): IDs of templates the new custom field will apply to if include_all is False.
|
|
28
|
+
configs (list, optional): A list of configuration objects for the new custom field.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
dict: The response from the API.
|
|
32
|
+
"""
|
|
33
|
+
data = {
|
|
34
|
+
"type": field_type,
|
|
35
|
+
"name": name,
|
|
36
|
+
"label": label,
|
|
37
|
+
"description": description,
|
|
38
|
+
"include_all": include_all,
|
|
39
|
+
"template_ids": template_ids,
|
|
40
|
+
"configs": configs
|
|
41
|
+
}
|
|
42
|
+
return _api.api_request('POST', 'add_case_field', data)
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
from . import _common
|
|
2
|
+
_api = _common.ApiConstructor()
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def add_case(section_id, title, template_id=None, type_id=None, priority_id=None, estimate=None, milestone_id=None, refs=None):
|
|
6
|
+
"""
|
|
7
|
+
Add a new test case to a specific section.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
section_id (str): The ID of the section.
|
|
11
|
+
title (str): The title of the test case.
|
|
12
|
+
template_id (int, optional): The ID of the template.
|
|
13
|
+
type_id (int, optional): The ID of the type.
|
|
14
|
+
priority_id (int, optional): The ID of the priority.
|
|
15
|
+
estimate (str, optional): The estimate for the test case.
|
|
16
|
+
milestone_id (int, optional): The ID of the milestone.
|
|
17
|
+
refs (str, optional): A comma-separated list of references.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
dict: The response from the API.
|
|
21
|
+
"""
|
|
22
|
+
data = {
|
|
23
|
+
"title": title,
|
|
24
|
+
"template_id": template_id,
|
|
25
|
+
"type_id": type_id,
|
|
26
|
+
"priority_id": priority_id,
|
|
27
|
+
"estimate": estimate,
|
|
28
|
+
"milestone_id": milestone_id,
|
|
29
|
+
"refs": refs
|
|
30
|
+
}
|
|
31
|
+
return _api.api_request('POST', f'add_case/{section_id}', data)
|
|
32
|
+
|
|
33
|
+
def get_case(case_id):
|
|
34
|
+
"""
|
|
35
|
+
Get details of a specific test case.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
case_id (str): The ID of the test case.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
dict: The response from the API.
|
|
42
|
+
"""
|
|
43
|
+
return _api.api_request('GET', f'get_case/{case_id}')
|
|
44
|
+
|
|
45
|
+
def get_cases(project_id, suite_id=None, section_id=None, filters=None):
|
|
46
|
+
"""
|
|
47
|
+
Get all test cases for a specific project, optionally filtered by suite, section, and other filters.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
project_id (str): The ID of the project.
|
|
51
|
+
suite_id (str, optional): The ID of the suite.
|
|
52
|
+
section_id (str, optional): The ID of the section.
|
|
53
|
+
filters (dict, optional): Additional filters for the request.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
list: A list of dictionaries containing the details of each test case.
|
|
57
|
+
"""
|
|
58
|
+
endpoint = f'get_cases/{project_id}'
|
|
59
|
+
if suite_id:
|
|
60
|
+
endpoint += f'&suite_id={suite_id}'
|
|
61
|
+
if section_id:
|
|
62
|
+
endpoint += f'§ion_id={section_id}'
|
|
63
|
+
if filters:
|
|
64
|
+
for key, value in filters.items():
|
|
65
|
+
endpoint += f'&{key}={value}'
|
|
66
|
+
return _api.api_request('GET', endpoint)
|
|
67
|
+
|
|
68
|
+
def update_case(case_id, title=None, template_id=None, type_id=None, priority_id=None, estimate=None, milestone_id=None, refs=None):
|
|
69
|
+
"""
|
|
70
|
+
Update an existing test case.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
case_id (str): The ID of the test case.
|
|
74
|
+
title (str, optional): The title of the test case.
|
|
75
|
+
template_id (int, optional): The ID of the template.
|
|
76
|
+
type_id (int, optional): The ID of the type.
|
|
77
|
+
priority_id (int, optional): The ID of the priority.
|
|
78
|
+
estimate (str, optional): The estimate for the test case.
|
|
79
|
+
milestone_id (int, optional): The ID of the milestone.
|
|
80
|
+
refs (str, optional): A comma-separated list of references.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
dict: The response from the API.
|
|
84
|
+
"""
|
|
85
|
+
data = {
|
|
86
|
+
"title": title,
|
|
87
|
+
"template_id": template_id,
|
|
88
|
+
"type_id": type_id,
|
|
89
|
+
"priority_id": priority_id,
|
|
90
|
+
"estimate": estimate,
|
|
91
|
+
"milestone_id": milestone_id,
|
|
92
|
+
"refs": refs
|
|
93
|
+
}
|
|
94
|
+
return _api.api_request('POST', f'update_case/{case_id}', data)
|
|
95
|
+
|
|
96
|
+
def delete_case(case_id):
|
|
97
|
+
"""
|
|
98
|
+
Delete a specific test case.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
case_id (str): The ID of the test case.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
dict: The response from the API.
|
|
105
|
+
"""
|
|
106
|
+
return _api.api_request('POST', f'delete_case/{case_id}')
|
|
107
|
+
|
|
108
|
+
def get_case_fields():
|
|
109
|
+
"""
|
|
110
|
+
Get all available test case fields.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
list: A list of dictionaries containing the details of each test case field.
|
|
114
|
+
"""
|
|
115
|
+
return _api.api_request('GET', 'get_case_fields')
|
|
116
|
+
|
|
117
|
+
def get_case_types():
|
|
118
|
+
"""
|
|
119
|
+
Get all available test case types.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
list: A list of dictionaries containing the details of each test case type.
|
|
123
|
+
"""
|
|
124
|
+
return _api.api_request('GET', 'get_case_types')
|
|
125
|
+
|
|
126
|
+
def get_history_for_case(case_id, limit=None, offset=None):
|
|
127
|
+
"""
|
|
128
|
+
Get the history for a specific test case.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
case_id (str): The ID of the test case.
|
|
132
|
+
limit (int, optional): The maximum number of history entries to return.
|
|
133
|
+
offset (int, optional): The number of history entries to skip before starting to collect the result set.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
list: A list of dictionaries containing the history of the test case.
|
|
137
|
+
"""
|
|
138
|
+
endpoint = f'get_history_for_case/{case_id}'
|
|
139
|
+
if limit:
|
|
140
|
+
endpoint += f'&limit={limit}'
|
|
141
|
+
if offset:
|
|
142
|
+
endpoint += f'&offset={offset}'
|
|
143
|
+
return _api.api_request('GET', endpoint)
|
|
144
|
+
|
|
145
|
+
def copy_cases_to_section(section_id, case_ids=None):
|
|
146
|
+
"""
|
|
147
|
+
Copy test cases to a specific section.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
section_id (str): The ID of the section.
|
|
151
|
+
case_ids (list, optional): A list of test case IDs to copy.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
dict: The response from the API.
|
|
155
|
+
"""
|
|
156
|
+
data = {
|
|
157
|
+
"case_ids": case_ids
|
|
158
|
+
}
|
|
159
|
+
return _api.api_request('POST', f'copy_cases_to_section/{section_id}', data)
|
|
160
|
+
|
|
161
|
+
def update_cases(suite_id, case_ids, section_id=None, title=None, template_id=None, type_id=None, priority_id=None, estimate=None, milestone_id=None, refs=None):
|
|
162
|
+
"""
|
|
163
|
+
Update multiple test cases.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
suite_id (str): The ID of the suite.
|
|
167
|
+
case_ids (list): A list of test case IDs to update.
|
|
168
|
+
section_id (str, optional): The ID of the section.
|
|
169
|
+
title (str, optional): The title of the test cases.
|
|
170
|
+
template_id (int, optional): The ID of the template.
|
|
171
|
+
type_id (int, optional): The ID of the type.
|
|
172
|
+
priority_id (int, optional): The ID of the priority.
|
|
173
|
+
estimate (str, optional): The estimate for the test cases.
|
|
174
|
+
milestone_id (int, optional): The ID of the milestone.
|
|
175
|
+
refs (str, optional): A comma-separated list of references.
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
dict: The response from the API.
|
|
179
|
+
"""
|
|
180
|
+
data = {
|
|
181
|
+
"case_ids": case_ids,
|
|
182
|
+
"section_id": section_id,
|
|
183
|
+
"title": title,
|
|
184
|
+
"template_id": template_id,
|
|
185
|
+
"type_id": type_id,
|
|
186
|
+
"priority_id": priority_id,
|
|
187
|
+
"estimate": estimate,
|
|
188
|
+
"milestone_id": milestone_id,
|
|
189
|
+
"refs": refs
|
|
190
|
+
}
|
|
191
|
+
return _api.api_request('POST', f'update_cases/{suite_id}', data)
|
|
192
|
+
|
|
193
|
+
def move_cases_to_section(section_id, suite_id, case_ids):
|
|
194
|
+
"""
|
|
195
|
+
Move test cases to a specific section.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
section_id (str): The ID of the section.
|
|
199
|
+
suite_id (str): The ID of the suite.
|
|
200
|
+
case_ids (list): A list of test case IDs to move.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
dict: The response from the API.
|
|
204
|
+
"""
|
|
205
|
+
data = {
|
|
206
|
+
"suite_id": suite_id,
|
|
207
|
+
"case_ids": case_ids
|
|
208
|
+
}
|
|
209
|
+
return _api.api_request('POST', f'move_cases_to_section/{section_id}', data)
|
|
210
|
+
|
|
211
|
+
def delete_cases(suite_id, case_ids, project_id, soft=0):
|
|
212
|
+
"""
|
|
213
|
+
Delete multiple test cases.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
suite_id (str): The ID of the suite.
|
|
217
|
+
case_ids (list): A list of test case IDs to delete.
|
|
218
|
+
project_id (str): The ID of the project.
|
|
219
|
+
soft (int, optional): Whether to perform a soft delete (default is 0).
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
dict: The response from the API.
|
|
223
|
+
"""
|
|
224
|
+
data = {
|
|
225
|
+
"case_ids": case_ids,
|
|
226
|
+
"project_id": project_id,
|
|
227
|
+
"soft": soft
|
|
228
|
+
}
|
|
229
|
+
return _api.api_request('POST', f'delete_cases/{suite_id}', data)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import logging as _logging
|
|
2
|
+
from . import _common
|
|
3
|
+
_api = _common.ApiConstructor()
|
|
4
|
+
|
|
5
|
+
# Print initializing message for file_name
|
|
6
|
+
print("{0} is initializing...".format(__file__))
|
|
7
|
+
|
|
8
|
+
def add(run_id=None, case_id=None, status_id=None, comment=None, version=None, elapsed=None, defects=None, assignedto_id=None):
|
|
9
|
+
"""
|
|
10
|
+
Add a test result for a specific test case in a test run.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
run_id (str): The ID of the test run.
|
|
14
|
+
case_id (str): The ID of the test case.
|
|
15
|
+
status_id (int): The status ID of the test result.
|
|
16
|
+
comment (str): A comment for the test result.
|
|
17
|
+
version (str): The version of the software under test.
|
|
18
|
+
elapsed (str): The time taken to execute the test.
|
|
19
|
+
defects (str): A comma-separated list of defects.
|
|
20
|
+
assignedto_id (int): The ID of the user the test is assigned to.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
bool: True if the test result was added successfully, False otherwise.
|
|
24
|
+
"""
|
|
25
|
+
data = {
|
|
26
|
+
"status_id": status_id,
|
|
27
|
+
"comment": comment,
|
|
28
|
+
"version": version,
|
|
29
|
+
"elapsed": elapsed,
|
|
30
|
+
"defects": defects,
|
|
31
|
+
"assignedto_id": assignedto_id
|
|
32
|
+
}
|
|
33
|
+
response = _api.api_request('POST', f'add_result_for_case/{run_id}/{case_id}', data)
|
|
34
|
+
print("Test result added successfully." if response else "Failed to add test result.")
|
|
35
|
+
if response is not None:
|
|
36
|
+
_logging.info(f"Test result added successfully. Response: {response}")
|
|
37
|
+
return True
|
|
38
|
+
else:
|
|
39
|
+
_logging.error(f"Failed to add test result. Response: {response}")
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
def get_plans(project_id):
|
|
43
|
+
"""
|
|
44
|
+
Get all test plans for a specific project.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
project_id (str): The ID of the project.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
list: A list of dictionaries containing the name, ID, and description of each test plan.
|
|
51
|
+
"""
|
|
52
|
+
response = _api.api_request('GET', f'get_plans/{project_id}')
|
|
53
|
+
return [{"name": plan["name"], "id": plan["id"], "description": plan["description"]} for plan in response['plans']] if response else []
|
|
54
|
+
|
|
55
|
+
def get_run_ids_from_plan(plan_id):
|
|
56
|
+
"""
|
|
57
|
+
Get all test run IDs from a specific test plan.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
plan_id (str): The ID of the test plan.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
list: A list of dictionaries containing the name, ID, and description of each test run.
|
|
64
|
+
"""
|
|
65
|
+
response = _api.api_request('GET', f'get_plan/{plan_id}')
|
|
66
|
+
return [{"name": run["name"], "id": run["id"], "description": run["description"]} for entry in response['entries'] for run in entry['runs']] if response else []
|
|
67
|
+
|
|
68
|
+
def get_run(run_id):
|
|
69
|
+
"""
|
|
70
|
+
Get details of a specific test run.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
run_id (str): The ID of the test run.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
dict: A dictionary containing the details of the test run.
|
|
77
|
+
"""
|
|
78
|
+
return _api.api_request('GET', f'get_run/{run_id}')
|
|
79
|
+
|
|
80
|
+
def get_case_ids_from_run(run_id):
|
|
81
|
+
"""
|
|
82
|
+
Get all test case IDs from a specific test run.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
run_id (str): The ID of the test run.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
list: A list of test case IDs.
|
|
89
|
+
"""
|
|
90
|
+
response = _api.api_request('GET', f'get_tests/{run_id}')
|
|
91
|
+
return [test['case_id'] for test in response['tests']] if response else []
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from . import _common
|
|
2
|
+
_api = _common.ApiConstructor()
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
# Print initializing message for file_name
|
|
7
|
+
print("{0} is initializing...".format(__file__))
|
|
8
|
+
|
|
9
|
+
def get_test(test_id):
|
|
10
|
+
"""
|
|
11
|
+
Get details of a specific test.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
test_id (str): The ID of the test.
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
dict: A dictionary containing the details of the test.
|
|
18
|
+
"""
|
|
19
|
+
return _api.api_request('GET', f'get_test/{test_id}')
|
|
20
|
+
|
|
21
|
+
def get_tests(run_id, status_id=None, limit=None, offset=None):
|
|
22
|
+
"""
|
|
23
|
+
Get all tests for a specific test run, optionally filtered by status, limit, and offset.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
run_id (str): The ID of the test run.
|
|
27
|
+
status_id (int, optional): The status ID to filter the tests.
|
|
28
|
+
limit (int, optional): The maximum number of tests to return.
|
|
29
|
+
offset (int, optional): The number of tests to skip before starting to collect the result set.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
list: A list of dictionaries containing the details of each test.
|
|
33
|
+
"""
|
|
34
|
+
endpoint = f'get_tests/{run_id}'
|
|
35
|
+
if status_id:
|
|
36
|
+
endpoint += f'&status_id={status_id}'
|
|
37
|
+
if limit:
|
|
38
|
+
endpoint += f'&limit={limit}'
|
|
39
|
+
if offset:
|
|
40
|
+
endpoint += f'&offset={offset}'
|
|
41
|
+
return _api.api_request('GET', endpoint)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: testrail_api_module
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A simple wrapper for the TestRail API
|
|
5
|
+
Author: Christian Thompson
|
|
6
|
+
Author-email: Matt Troutman <github@trtmn.com>
|
|
7
|
+
Project-URL: Homepage, https://github.com/trtmn/testrail_api_module
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: requests
|
|
10
|
+
Dynamic: license-file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/testrail_api_module/__init__.py
|
|
5
|
+
src/testrail_api_module/_common.py
|
|
6
|
+
src/testrail_api_module/attachments.py
|
|
7
|
+
src/testrail_api_module/bdd.py
|
|
8
|
+
src/testrail_api_module/case_fields.py
|
|
9
|
+
src/testrail_api_module/case_types.py
|
|
10
|
+
src/testrail_api_module/cases.py
|
|
11
|
+
src/testrail_api_module/configurations.py
|
|
12
|
+
src/testrail_api_module/datasets.py
|
|
13
|
+
src/testrail_api_module/groups.py
|
|
14
|
+
src/testrail_api_module/milestones.py
|
|
15
|
+
src/testrail_api_module/plans.py
|
|
16
|
+
src/testrail_api_module/priorities.py
|
|
17
|
+
src/testrail_api_module/projects.py
|
|
18
|
+
src/testrail_api_module/reports.py
|
|
19
|
+
src/testrail_api_module/result_fields.py
|
|
20
|
+
src/testrail_api_module/results.py
|
|
21
|
+
src/testrail_api_module/roles.py
|
|
22
|
+
src/testrail_api_module/runs.py
|
|
23
|
+
src/testrail_api_module/sections.py
|
|
24
|
+
src/testrail_api_module/shared_steps.py
|
|
25
|
+
src/testrail_api_module/statuses.py
|
|
26
|
+
src/testrail_api_module/suites.py
|
|
27
|
+
src/testrail_api_module/templates.py
|
|
28
|
+
src/testrail_api_module/tests.py
|
|
29
|
+
src/testrail_api_module/users.py
|
|
30
|
+
src/testrail_api_module/variables.py
|
|
31
|
+
src/testrail_api_module.egg-info/PKG-INFO
|
|
32
|
+
src/testrail_api_module.egg-info/SOURCES.txt
|
|
33
|
+
src/testrail_api_module.egg-info/dependency_links.txt
|
|
34
|
+
src/testrail_api_module.egg-info/requires.txt
|
|
35
|
+
src/testrail_api_module.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
testrail_api_module
|