Skip to content

Commit e2e1e98

Browse files
committed
[tl-tests] tests updated for XMLRPC
+ added base class for testing, with minimal asserts + test for call: getTestProjectByName + test for call: getProjectTestPlans
1 parent 91bc059 commit e2e1e98

6 files changed

Lines changed: 426 additions & 28 deletions

File tree

testlinktests/core/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"""
88

99

10+
from testlinktests.core import test_info
1011
from testlinktests.core import utils
1112

1213

13-
__all__ = ['utils']
14+
__all__ = ['test_info', 'utils']

testlinktests/core/test_info.py

Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
# -*- coding: utf-8 -*-
2+
"""Base module for inherit new Test Suites"""
3+
4+
5+
import os
6+
import re
7+
import time
8+
import pytest
9+
from qatestlink.core.testlink_manager import TLManager
10+
11+
12+
ASSERT_MSG_DEFAULT = "Fails at '{}': actual={}, expected={}"
13+
ASSERT_REGEX_URL = r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+" # noqa: E501
14+
15+
16+
class TestInfoBase(object):
17+
"""Base class for inherit new Test classes"""
18+
19+
tlm = None
20+
log = None
21+
22+
@classmethod
23+
def setup_class(cls, **kwargs):
24+
"""Configure 'cls.attribute'. If name start with 'test_' and have
25+
decorator skipIf with value True, then not open bot
26+
"""
27+
tests_methods = []
28+
skip_methods = []
29+
skip_force = kwargs.get('skip_force')
30+
for method_name in dir(cls):
31+
if method_name.startswith("test_"):
32+
method = getattr(cls, method_name)
33+
tests_methods.append(method)
34+
if 'skipIf' in dir(method) and method.skipIf.args[0]:
35+
skip_methods.append(method)
36+
if tests_methods == skip_methods or skip_force:
37+
pytest.skip("Testsuite skipped")
38+
39+
def setup_method(self, test_method, **kwargs):
40+
"""Configure self.attribute.
41+
If skipIf mark applied and True as first param for args tuple
42+
then not open bot
43+
"""
44+
if 'skipIf' in dir(test_method) and test_method.skipIf.args[0]:
45+
pytest.skip(test_method.skipIf.args[1])
46+
return
47+
settings = kwargs.get('settings')
48+
tlm = kwargs.get('tlm')
49+
if settings is None and tlm is None:
50+
raise Exception(
51+
("Not settings or TLManager "
52+
"instance provided, read README first"))
53+
if tlm is None:
54+
tlm = TLManager(settings=settings)
55+
self.tlm = tlm
56+
self.log = tlm.log
57+
self.log.info("Started testcase named='{}'".format(
58+
test_method.__name__))
59+
60+
def teardown_method(self, test_method):
61+
"""Unload self.attribute"""
62+
self.log.info("Finished testcase named='{}'".format(
63+
test_method.__name__))
64+
65+
@classmethod
66+
def add_property(cls, name, value=None):
67+
"""Add property to test instance using param 'name', will setup
68+
None if any value it's passed by param
69+
"""
70+
setattr(cls, name, value)
71+
72+
def timer(self, wait=5, print_each=5):
73+
"""Timer to sleep browser on testcases
74+
75+
Keyword Arguments:
76+
wait {int} -- seconds to wait (default: {5})
77+
print_each {int} -- print message each seconds, must be divisible
78+
by 5, negatives are accepted (default: {5})
79+
80+
Raises:
81+
Exception -- [description]
82+
"""
83+
msg_err = "Timer can't works if print_each param isn't divisible by 1"
84+
if (print_each % 1) != 0:
85+
raise Exception(msg_err)
86+
while wait > 0:
87+
self.sleep(print_each)
88+
wait -= print_each
89+
90+
def sleep(self, wait=0):
91+
"""Just call to native python time.sleep method
92+
93+
Keyword Arguments:
94+
wait {int} -- Wait time on Runtime execution before execute
95+
next lane of code (default: {0})
96+
"""
97+
if wait > 0:
98+
time.sleep(wait)
99+
100+
def assert_equals(self, actual, expected, msg=None):
101+
"""Allow to compare 2 values and check if 1st it's equals to
102+
2nd value
103+
"""
104+
if not msg:
105+
msg = ASSERT_MSG_DEFAULT.format(
106+
"assert_equals", actual, expected)
107+
if actual != expected:
108+
raise AssertionError(actual, expected, msg)
109+
return True
110+
111+
def assert_not_equals(self, actual, expected, msg=None):
112+
"""Allow to compare 2 value to check if 1st isn't equals to
113+
2nd value
114+
"""
115+
if not msg:
116+
msg = ASSERT_MSG_DEFAULT.format(
117+
"assert_not_equals", actual, expected)
118+
if actual == expected:
119+
raise AssertionError(actual, expected, msg)
120+
return True
121+
122+
def assert_equals_url(self, actual, expected, msg=None, wait=0):
123+
"""Allow to compare 2 urls and check if 1st it's equals to 2nd url
124+
125+
Arguments:
126+
actual {type} -- actual value
127+
expected {type} -- expected value
128+
129+
Keyword Arguments:
130+
wait {int} -- Wait time on Runtime execution before execute
131+
next lane of code (default: {0})
132+
133+
Raises:
134+
AssertionError -- [description]
135+
"""
136+
if not msg:
137+
msg = ASSERT_MSG_DEFAULT.format(
138+
"assert_equals_url", actual, expected)
139+
self.sleep(wait)
140+
if actual != expected:
141+
raise AssertionError(actual, expected, msg)
142+
return True
143+
144+
def assert_not_equals_url(self, actual, expected, msg=None, wait=0):
145+
"""Allow to compare 2 urls to check if 1st isn't equals to 2nd url"""
146+
if not msg:
147+
msg = ASSERT_MSG_DEFAULT.format(
148+
"assert_not_equals_url", actual, expected)
149+
self.sleep(wait)
150+
if actual == expected:
151+
raise AssertionError(actual, expected, msg)
152+
return True
153+
154+
def assert_contains_url(self, actual, contains, msg=None, wait=0):
155+
"""Allow to compare 2 urls and check if 1st contains 2nd url"""
156+
if not msg:
157+
msg = ASSERT_MSG_DEFAULT.format(
158+
"assert_contains_url", actual, contains)
159+
self.sleep(wait)
160+
if actual not in contains:
161+
raise AssertionError(actual, contains, msg)
162+
return True
163+
164+
def assert_not_contains_url(self, actual, contains, msg=None, wait=0):
165+
"""Allow to compare 2 urls and check if 1st not contains 2nd url"""
166+
if not msg:
167+
msg = ASSERT_MSG_DEFAULT.format(
168+
"assert_not_contains_url", actual, contains)
169+
self.sleep(wait)
170+
if actual in contains:
171+
raise AssertionError(actual, contains, msg)
172+
return True
173+
174+
def assert_is_instance(self, instance, class_type, msg=None):
175+
"""Allow to encapsulate method assertIsInstance(obj, cls, msg='')"""
176+
if not msg:
177+
msg = ASSERT_MSG_DEFAULT.format(
178+
"assert_is_instance", instance, class_type)
179+
if not isinstance(class_type, type):
180+
class_type = type(class_type)
181+
if not isinstance(instance, class_type):
182+
raise AssertionError(instance, class_type, msg)
183+
return True
184+
185+
def assert_raises(self, expected_exception, function, *args, **kwargs):
186+
"""Allow to encapsulate pytest.raises method(
187+
*args=(
188+
expected_exception,
189+
function,
190+
),
191+
**kwargs={
192+
msg: ASSERT_MSG_DEFAULT
193+
}
194+
)
195+
"""
196+
msg = kwargs.get('msg')
197+
if not msg:
198+
msg = ASSERT_MSG_DEFAULT.format(
199+
"assert_raises",
200+
"TODO:not implemented value",
201+
expected_exception)
202+
return pytest.raises(expected_exception, function, *args, **kwargs)
203+
204+
def assert_greater(self, actual, greater, msg=None):
205+
"""Allow to encapsulate method assertGreater(a, b, msg=msg)"""
206+
if not msg:
207+
msg = ASSERT_MSG_DEFAULT.format(
208+
"assert_greater", actual, greater)
209+
if actual < greater:
210+
raise AssertionError(actual, greater, msg)
211+
return True
212+
213+
def assert_lower(self, actual, lower, msg=None):
214+
"""Allow to encapsulate method assertLower(a, b, msg=msg)"""
215+
if not msg:
216+
msg = ASSERT_MSG_DEFAULT.format(
217+
"assert_greater", actual, lower)
218+
if actual > lower:
219+
raise AssertionError(actual, lower, msg)
220+
return True
221+
222+
def assert_in(self, actual, valid_values, msg=None):
223+
"""Allow to compare if value it's in to 2nd list of values"""
224+
if not msg:
225+
msg = ASSERT_MSG_DEFAULT.format(
226+
"assert_in", actual, valid_values)
227+
if actual not in valid_values:
228+
raise AssertionError(actual, valid_values, msg)
229+
return True
230+
231+
def assert_not_in(self, actual, invalid_values, msg=None):
232+
"""Allow to compare if value it's not in to 2nd list of values"""
233+
if not msg:
234+
msg = ASSERT_MSG_DEFAULT.format(
235+
"assert_in", actual, invalid_values)
236+
if actual in invalid_values:
237+
raise AssertionError(actual, invalid_values, msg)
238+
return True
239+
240+
def assert_regex(self, actual, pattern, msg=None):
241+
"""Allow to compare if value match pattern"""
242+
if not msg:
243+
msg = ASSERT_MSG_DEFAULT.format(
244+
"assert_regex", actual, pattern)
245+
is_match = re.match(pattern, actual)
246+
if not is_match:
247+
raise AssertionError(actual, pattern, msg)
248+
return True
249+
250+
def assert_not_regex(self, actual, pattern, msg=None):
251+
"""Allow to compare if value not match pattern"""
252+
if not msg:
253+
msg = ASSERT_MSG_DEFAULT.format(
254+
"assert_not_regex", actual, pattern)
255+
is_match = re.match(pattern, actual)
256+
if is_match:
257+
raise AssertionError(actual, pattern, msg)
258+
return True
259+
260+
def assert_regex_url(self, actual, pattern=None, msg=None):
261+
"""Allow to compare if value match url pattern, can use
262+
custom pattern
263+
"""
264+
if not msg:
265+
msg = ASSERT_MSG_DEFAULT.format(
266+
"assert_regex_url", actual, pattern)
267+
if not pattern:
268+
pattern = ASSERT_REGEX_URL
269+
return self.assert_regex(actual, pattern, msg=msg)
270+
271+
def assert_path_exist(self, actual, is_dir=True, msg=None):
272+
"""Allow to check if path exist, can check if is_dir also"""
273+
if not msg:
274+
msg = ASSERT_MSG_DEFAULT.format(
275+
"assert_path_exist",
276+
actual,
277+
"is_dir={}".format(is_dir))
278+
if not os.path.exists(actual):
279+
raise AssertionError(actual, "NEED_PATH_FOUND", msg)
280+
_is_dir = os.path.isdir(actual)
281+
if is_dir:
282+
if not _is_dir:
283+
raise AssertionError(actual, "NEED_PATH_IS_DIR", msg)
284+
else:
285+
if _is_dir:
286+
raise AssertionError(actual, "NEED_PATH_NOT_DIR", msg)
287+
return True
288+
289+
def assert_path_not_exist(self, actual, msg=None):
290+
"""Allow to check if path not exist, can check if is_dir also"""
291+
if not msg:
292+
msg = ASSERT_MSG_DEFAULT.format(
293+
"assert_path_not_exist", actual, "")
294+
if os.path.exists(actual):
295+
raise AssertionError(actual, "NEED_PATH_NOT_FOUND", msg)
296+
return True
297+
298+
def assert_true(self, actual, msg=None):
299+
"""Allow to compare and check if value it's equals to 'True'"""
300+
if not msg:
301+
msg = ASSERT_MSG_DEFAULT.format(
302+
"assert_true", actual, "")
303+
self.assert_is_instance(actual, bool)
304+
self.assert_equals(actual, True, msg=msg)
305+
return True
306+
307+
def assert_false(self, actual, msg=None):
308+
"""Allow to compare and check if value it's equals to 'False'"""
309+
if not msg:
310+
msg = ASSERT_MSG_DEFAULT.format(
311+
"assert_false", actual, "")
312+
self.assert_is_instance(actual, bool)
313+
self.assert_equals(actual, False, msg=msg)
314+
return True
315+
316+
def assert_none(self, actual, msg=None):
317+
"""Allow to compare and check if value it's equals to 'None'"""
318+
if not msg:
319+
msg = ASSERT_MSG_DEFAULT.format(
320+
"assert_false", actual, "")
321+
return self.assert_equals(actual, None, msg=msg)
322+
323+
def assert_not_none(self, actual, msg=None):
324+
"""Allow to compare and check if value it's not equals to 'None'"""
325+
if not msg:
326+
msg = ASSERT_MSG_DEFAULT.format(
327+
"assert_false", actual, "")
328+
return self.assert_not_equals(actual, None, msg=msg)
Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,35 @@
55
import pytest
66
from qatestlink.core.exceptions.response_exception import ResponseException
77
from qatestlink.core.testlink_manager import TLManager
8-
from testlinktests.core.utils import settings
8+
from testlinktests.core.test_info import TestInfoBase
9+
from testlinktests.core.utils import settings as CFG
910

1011

11-
CONFIG = settings(
12+
CONFIG = CFG(
1213
file_path="testlinktests/configs/",
1314
file_name="settings.example.json"
1415
)
1516

1617

17-
class TestMethods(object):
18+
class TestCheckDevKey(TestInfoBase):
1819
"""TODO: doc class"""
1920

2021
def setup_method(self, test_method, **kwargs):
2122
"""TODO: doc method"""
22-
if 'skipIf' in dir(test_method) and test_method.skipIf.args[0]:
23-
pytest.skip(test_method.skipIf.args[1])
24-
return
25-
self.tlm = TLManager(settings=CONFIG)
23+
super(TestCheckDevKey, self).setup_method(
24+
test_method, **{"tlm": TLManager(settings=CONFIG)})
2625

2726
def test_checkdevkey(self):
2827
"""TestCase: test_checkdevkey
2928
Login success with valid config
3029
"""
30+
msg_error = "API_KEY it's invalid when must be valid"
3131
is_logged = self.tlm.api_login()
32-
if not is_logged:
33-
raise AssertionError(
34-
"API_KEY it's invalid when must be valid")
32+
self.assert_true(is_logged, msg=msg_error)
3533

3634
@pytest.mark.raises(exception=ResponseException)
3735
def test_raises_checkdevkey(self):
3836
"""TestCase: test_raises_checkdevkey"""
37+
msg_error = "API_KEY it's invalid when must be valid"
3938
is_logged = self.tlm.api_login(dev_key='willfail')
40-
if is_logged:
41-
raise AssertionError(
42-
"API_KEY it's invalid when must be valid")
39+
self.assert_false(is_logged, msg=msg_error)

0 commit comments

Comments
 (0)