687bdd580a95062e980762d0f5ceae79357df4df
[idea/community.git] / python / educational-python / resources / fileTemplates / internal / test_helper.py.ft
1 import sys
2
3
4 def get_file_text(path):
5     """ Returns file text by path"""
6     file_io = open(path, "r")
7     text = file_io.read()
8     file_io.close()
9     return text
10
11
12 def get_file_output(encoding="utf-8", path=sys.argv[-1]):
13     """
14     Returns answer file output
15     :param encoding: to decode output in python3
16     :param path: path of file to execute
17     :return: list of strings
18     """
19     import subprocess
20
21     proc = subprocess.Popen([sys.executable, path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
22     return list(map(lambda x: str(x.decode(encoding)), proc.communicate()[0].splitlines()))
23
24
25 def test_file_importable():
26     """ Tests there is no obvious syntax errors"""
27     path = sys.argv[-1]
28     if not path.endswith(".py"):
29         import os
30
31         parent = os.path.abspath(os.path.join(path, os.pardir))
32         python_files = [f for f in os.listdir(parent) if os.path.isfile(os.path.join(parent, f)) and f.endswith(".py")]
33         for python_file in python_files:
34             if python_file == "tests.py": continue
35             check_importable_path(os.path.join(parent, python_file))
36         return
37     check_importable_path(path)
38
39
40 def check_importable_path(path):
41     """ Checks that file is importable.
42         Reports failure otherwise.
43     """
44     try:
45         import_file(path)
46     except:
47         failed("The file contains syntax errors", test_file_importable.__name__)
48         return
49     passed(test_file_importable.__name__)
50
51
52 def import_file(path):
53     """ Returns imported file """
54     if sys.version_info[0] == 2 or sys.version_info[1] < 3:
55         import imp
56
57         return imp.load_source("tmp", path)
58     elif sys.version_info[0] == 3:
59         import importlib.machinery
60
61         return importlib.machinery.SourceFileLoader("tmp", path).load_module("tmp")
62
63
64 def import_task_file():
65     """ Returns imported file.
66         Imports file from which check action was run
67     """
68     path = sys.argv[-1]
69     return import_file(path)
70
71
72 def test_is_not_empty():
73     """
74         Checks that file is not empty
75     """
76     path = sys.argv[-1]
77     file_text = get_file_text(path)
78
79     if len(file_text) > 0:
80         passed()
81     else:
82         failed("The file is empty. Please, reload the task and try again.")
83
84
85 def test_is_initial_text(error_text="You should modify the file"):
86     """
87         Checks that file was modified
88     """
89     path = sys.argv[-1]
90     text = get_initial_text(path)
91     file_text = get_file_text(path)
92
93     if file_text.strip() == text.strip():
94         failed(error_text)
95     else:
96         passed()
97
98
99 def get_initial_text(path):
100     """
101         Returns the initial task text
102     """
103     course_lib = sys.argv[-2]
104
105     import os
106     # path format is "project_root/lessonX/taskY/file.py"
107     task_index = path.rfind(os.sep, 0, path.rfind(os.sep))
108     index = path.rfind(os.sep, 0, task_index)
109     relative_path = path[index + 1:]
110     initial_file_path = os.path.join(course_lib, relative_path)
111     return get_file_text(initial_file_path)
112
113
114 def test_text_equals(text, error_text):
115     """
116         Checks that answer equals text.
117     """
118     path = sys.argv[-1]
119     file_text = get_file_text(path)
120
121     if file_text.strip() == text:
122         passed()
123     else:
124         failed(error_text)
125
126
127 def test_answer_placeholders_text_deleted(error_text="Don't just delete task text"):
128     """
129         Checks that all answer placeholders are not empty
130     """
131     windows = get_answer_placeholders()
132
133     for window in windows:
134         if len(window) == 0:
135             failed(error_text)
136             return
137     passed()
138
139
140 def set_congratulation_message(message):
141     """ Overrides default 'Congratulations!' message """
142     print("#educational_plugin CONGRATS_MESSAGE " + message)
143
144
145 def failed(message="Please, reload the task and try again.", name=None):
146     """ Reports failure """
147     if not name:
148         name = sys._getframe().f_back.f_code.co_name
149     print("#educational_plugin " + name + " FAILED + " + message)
150
151
152 def passed(name=None):
153     """ Reports success """
154     if not name:
155         name = sys._getframe().f_back.f_code.co_name
156     print("#educational_plugin " + name + " test OK")
157
158
159 def get_answer_placeholders():
160     """
161         Returns all answer placeholders text
162     """
163     prefix = "#educational_plugin_window = "
164     path = sys.argv[-1]
165     import os
166
167     file_name_without_extension = os.path.splitext(path)[0]
168     windows_path = file_name_without_extension + "_windows"
169     windows = []
170     f = open(windows_path, "r")
171     window_text = ""
172     first = True
173     for line in f.readlines():
174         if line.startswith(prefix):
175             if not first:
176                 windows.append(window_text.strip())
177             else:
178                 first = False
179             window_text = line[len(prefix):]
180         else:
181             window_text += line
182
183     if window_text:
184         windows.append(window_text.strip())
185
186     f.close()
187     return windows
188
189
190 def run_common_tests(error_text="Please, reload file and try again"):
191     test_is_initial_text()
192     test_is_not_empty()
193     test_answer_placeholders_text_deleted()
194     test_file_importable()