forked from datacamp/pythonwhat
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTest.py
More file actions
188 lines (144 loc) · 6.03 KB
/
Test.py
File metadata and controls
188 lines (144 loc) · 6.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import re
import numpy as np
import pandas as pd
from pythonwhat.tasks import *
from protowhat.Test import Test
"""
This file contains all tests that can be done on specific objects. All tests are represented as
an object. Tests that are alike can inherit from the same superclass. A test is first initialized
and can then be performed by calling the 'test()' function. The result will be stored inside
the result boolean. A test contains a failure message, which can be used by the reporter to
show when the test failed.
"""
# Testing definition
class DefinedProcessTest(Test):
def __init__(self, name, process, feedback):
super().__init__(feedback)
self.name = name
self.process = process
def test(self):
self.result = isDefinedInProcess(self.name, self.process)
class DefinedCollTest(Test):
"""
Check if an object with a certain name is defined in a collection.
Attributes:
feedback (str): A string containing the failure message in case the test fails.
name (str): Contains the name of the object that is searched for.
collection (list/dict/set): Contains any object on which the 'in' operator can be performed.
result (bool): True if the test succeed, False if it failed. None if it hasn't been tested yet.
"""
def __init__(self, name, collection, feedback):
super().__init__(feedback)
self.name = name
self.collection = collection
def test(self):
self.result = self.name in self.collection
class DefinedCollProcessTest(Test):
def __init__(self, name, key, process, feedback):
super().__init__(feedback)
self.name = name
self.key = key
self.process = process
def test(self):
self.result = isDefinedCollInProcess(self.name, self.key, self.process)
# Testing class
class InstanceProcessTest(Test):
def __init__(self, name, klass, process, feedback):
super().__init__(feedback)
self.name = name
self.klass = klass
self.process = process
def test(self):
self.result = isInstanceInProcess(self.name, self.klass, self.process)
# Testing equality
class EqualTest(Test):
"""
Check if two objects are equal. Equal means the objects are exactly the same.
This test should only be used with numeric variables (for now).
Attributes:
feedback (str): A string containing the failure message in case the test fails.
obj1 (str): The first object that should be compared with.
obj2 (str): This object is compared to obj1.
result (bool): True if the test succeed, False if it failed. None if it hasn't been tested yet.
"""
def __init__(self, obj1, obj2, feedback, func=None):
super().__init__(feedback)
self.obj1 = obj1
self.obj2 = obj2
self.func = func if func is not None else is_equal
def test(self):
"""
Perform the actual test. result is set to False if the objects differ, True otherwise.
"""
self.result = np.array(self.func(self.obj1, self.obj2)).all()
# Helpers for testing equality
def areinstance(x, y, tuple_of_classes):
return isinstance(x, tuple_of_classes) and isinstance(y, tuple_of_classes)
# For equality of ndarrays, list, dicts, pd Series and pd DataFrames:
# First try to the faster equality functions. If these don't pass,
# Run the assertions that are typically slower.
def is_equal(x, y):
try:
if areinstance(x, y, (Exception,)):
# Types of errors don't matter (this is debatable)
return str(x) == str(y)
if areinstance(x, y, (np.ndarray, dict, list, tuple)):
if np.array_equal(x, y):
return True
np.testing.assert_equal(x, y)
return True
elif areinstance(x, y, (map, filter)):
return np.array_equal(list(x), list(y))
elif areinstance(x, y, (pd.DataFrame,)):
if x.equals(y):
return True
pd.util.testing.assert_frame_equal(x, y)
return True
elif areinstance(x, y, (pd.Series,)):
if x.equals(y):
return True
pd.util.testing.assert_series_equal(x, y)
return True
else:
return x == y
except Exception:
return False
# Others
class BiggerTest(EqualTest):
"""
Check if the first object is greater than another.
"""
def __init__(self, *args):
super().__init__(*args, func=lambda obj1, obj2: obj1 > obj2)
class StringContainsTest(Test):
"""
Check if a string is present in a text. Can use literal strings or a regex.
Attributes:
feedback (str): A string containing the failure message in case the test fails.
string (regex/str): String or regular expression which is searched for.
search_string (str): The text in which is searched.
pattern (bool): If set to True, string is matched with a regex. Literal otherwise.
result (bool): True if the test succeed, False if it failed. None if it hasn't been tested yet.
"""
def __init__(self, string, search_string, pattern, feedback):
"""
Initialize with a string to look for, a string to search and whether or not to look for a pattern.
Args:
string (regex/str): The string to look for will be set to this.
search_string (str): The string to search in will be set to this.
pattern (bool): The pattern boolean will be set to this.
feedback (str): The failure message will be set to this.
"""
super().__init__(feedback)
self.string = string
self.search_string = search_string
self.pattern = pattern
def test(self):
"""
Perform the actual test. result will be True if string is found (whether or not with a pattern),
False otherwise.
"""
if self.pattern:
self.result = re.search(self.search_string, self.string) is not None
else:
self.result = self.string.find(self.search_string) is not -1