Skip to content

Commit c4f10da

Browse files
vuldercjdb
authored andcommitted
Adds initial tests using the internal layout
1 parent 1d7eedd commit c4f10da

File tree

7 files changed

+458
-54
lines changed

7 files changed

+458
-54
lines changed

internal/__init__.py

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Main Title
2+
3+
_Skeleton instructions are typeset in italic text._
4+
5+
## Section with user content: provided by the user
6+
7+
_ Example section where user text is in the header _
8+
9+
## Missing mid section
10+
11+
_ This section could be missing in the middle of the topics _
12+
13+
## Italics text should be updated
14+
15+
_ Wrong old italics text. _
16+
17+
## Meta text with line breaks
18+
19+
_ Some text here
20+
some after the line break _
21+
22+
## Missing end section
23+
24+
_ This section could be missing at the end of the document _
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Main Title
2+
3+
_Skeleton instructions are typeset in italic text._
4+
5+
## Section with user content: provided by the user
6+
7+
_ Example section where user text is in the header _
8+
9+
## Italics text should be updated
10+
11+
_ Updated italics text. _
12+
13+
## Meta text with line breaks
14+
15+
_ Some text here
16+
some after the line break _
17+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Main Title
2+
3+
_Skeleton instructions are typeset in italic text._
4+
5+
## Section with user content: provided by the user
6+
7+
_ Example section where user text is in the header _
8+
9+
## Missing mid section
10+
11+
_ This section could be missing in the middle of the topics _
12+
13+
## Italics text should be updated
14+
15+
_ Updated italics text. _
16+
17+
## Meta text with line breaks
18+
19+
_ Some text here
20+
some after the line break _
21+
22+
## Missing end section
23+
24+
_ This section could be missing at the end of the document _
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Main Title
2+
3+
_Skeleton instructions are typeset in italic text._
4+
5+
## Section with user content: This is provided by the user
6+
7+
_ Example section where user text is in the header _
8+
9+
Users can add different content here.
10+
<table>
11+
</table>
12+
13+
## Missing mid section
14+
15+
_ This section could be missing in the middle of the topics _
16+
17+
## Italics text should be updated
18+
19+
_ Updated italics text. _
20+
21+
## Meta text with line breaks
22+
23+
_ Some text here
24+
some after the line break _
25+
26+
## Missing end section
27+
28+
_ This section could be missing at the end of the document _

internal/tests/topic_updater_test.py

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
"""
2+
Testing module for the topic_updater script. This modules tests whether the
3+
abstractions, SectionHeading, Skeleton, which are used in the script correctly
4+
work.
5+
"""
6+
from itertools import dropwhile
7+
from pathlib import Path
8+
import copy
9+
import os
10+
import unittest
11+
12+
import mock
13+
14+
import topic_updater as tu
15+
16+
TEST_INPUTS = Path("tests/TEST_INPUTS/")
17+
18+
19+
class TestSectionHeading(unittest.TestCase):
20+
"""
21+
Tests the section heading class, which represents a specific secion heading
22+
in a topic markdown.
23+
"""
24+
@classmethod
25+
def setUpClass(cls):
26+
""" Setup example section header. """
27+
cls.section_title = "## Section Title"
28+
cls.test_meta_text_line0 = "_ Some meta text _" + os.linesep
29+
cls.test_meta_text_line1 = "_ Another line meta text _" + os.linesep
30+
31+
cls.new_heading = tu.SectionHeading(cls.section_title)
32+
cls.new_heading.append_meta_text(cls.test_meta_text_line0)
33+
34+
def test_basic_construction(self):
35+
""" Checks if we setup the basic section header correclty. """
36+
new_heading = copy.deepcopy(self.new_heading)
37+
38+
self.assertEqual(new_heading.header_text, self.section_title)
39+
self.assertEqual(new_heading.meta_text, [self.test_meta_text_line0])
40+
41+
new_heading.append_meta_text(self.test_meta_text_line1)
42+
43+
self.assertEqual(
44+
new_heading.meta_text,
45+
[self.test_meta_text_line0, self.test_meta_text_line1])
46+
47+
def test_meta_text_to_line_conversion(self):
48+
""" Checks if we correctly generate meta text. """
49+
new_heading = copy.deepcopy(self.new_heading)
50+
new_heading.append_meta_text(self.test_meta_text_line1)
51+
52+
meta_text_lines = new_heading.convert_meta_text_to_lines()
53+
54+
self.assertEqual(meta_text_lines[0], os.linesep,
55+
"First line should be only a linesep.")
56+
self.assertEqual(meta_text_lines[1], self.test_meta_text_line0)
57+
self.assertEqual(
58+
meta_text_lines[2], self.test_meta_text_line1 + os.linesep,
59+
"The last meta line should have an additional line separator")
60+
61+
62+
class TestSkeleton(unittest.TestCase):
63+
"""
64+
Tests the skeleton class which loads the topic skeleton from a file and
65+
parses it.
66+
"""
67+
@classmethod
68+
def setUpClass(cls):
69+
""" Setup small test skeleton which contains all edge cases. """
70+
cls.test_skeleton = tu.Skeleton(TEST_INPUTS / "test_skeleton.md")
71+
72+
def test_actual_skeleton_parse(self):
73+
"""
74+
Checks that we can fully parse the actual skeleton.
75+
"""
76+
offset_to_main_folder = "../../../"
77+
actual_skeleton = tu.Skeleton(TEST_INPUTS / offset_to_main_folder /
78+
"skeleton.md")
79+
80+
self.assertEqual(actual_skeleton.get_title_heading().header_text,
81+
"# Module name: topic name")
82+
headings = list(
83+
map(lambda heading: heading.header_text, actual_skeleton.headings))
84+
self.assertEqual(headings[0], "# Module name: topic name")
85+
self.assertEqual(headings[1], "## Overview")
86+
87+
self.assertEqual(headings[-2], "### Points to cover")
88+
self.assertEqual(headings[-1], "## Further studies")
89+
90+
def test_heading_lookup(self):
91+
"""
92+
Checks if we can lookup different section headings in the skeleton.
93+
"""
94+
section_with_user_content = self.test_skeleton.lookup_heading(
95+
"## Section with user content:")
96+
missing_mid = self.test_skeleton.lookup_heading(
97+
"## Missing mid section")
98+
99+
self.assertEqual(section_with_user_content.header_text,
100+
"## Section with user content: provided by the user")
101+
self.assertEqual(
102+
section_with_user_content.meta_text[0].rstrip(),
103+
"_ Example section where user text is in the header _")
104+
105+
self.assertEqual(missing_mid.header_text, "## Missing mid section")
106+
self.assertEqual(
107+
missing_mid.meta_text[0].rstrip(),
108+
"_ This section could be missing in the middle of the topics _")
109+
110+
def test_title_heading_lookup(self):
111+
"""
112+
Checks if we get the correct title heading from the test skeleton.
113+
"""
114+
self.assertEqual(self.test_skeleton.get_title_heading().header_text,
115+
"# Main Title")
116+
self.assertEqual(
117+
self.test_skeleton.get_title_heading().meta_text[0],
118+
"_Skeleton instructions are typeset in italic text._" + os.linesep)
119+
120+
def test_that_meta_text_with_linebreaks_inbetween_meta_markers_parse(self):
121+
"""
122+
Checks that we correctly parse meta text that stretches over multiple
123+
lines.
124+
"""
125+
multi_line_meta_heading = self.test_skeleton.lookup_heading(
126+
"## Meta text with line breaks")
127+
128+
self.assertEqual(multi_line_meta_heading.meta_text[0],
129+
"_ Some text here" + os.linesep)
130+
self.assertEqual(multi_line_meta_heading.meta_text[1],
131+
"some after the line break _" + os.linesep)
132+
133+
134+
class TestSkeletonTopicUpdates(unittest.TestCase):
135+
"""
136+
Test skeleton topic update function. This test tries to cover different
137+
scenarios that could occure during topic updates and verifies that we
138+
handle them correctly.
139+
"""
140+
@classmethod
141+
def setUpClass(cls):
142+
""" Setup small test skeleton which contains all edge cases. """
143+
cls.test_skeleton = tu.Skeleton(TEST_INPUTS / "test_skeleton.md")
144+
145+
def test_not_to_override_user_provided_heading_text(self):
146+
"""
147+
Checks that the update method does not override user provided text,
148+
which is part of some section headings.
149+
"""
150+
topic_file_path = TEST_INPUTS / "user_content_heading_topic.md"
151+
with open(topic_file_path, "r") as topic_file:
152+
updated_topic_lines = self.test_skeleton.update_topic_meta_text(
153+
topic_file)
154+
155+
start_test_scope_lines = list(
156+
dropwhile(
157+
lambda line: not line.startswith(
158+
"## Section with user content:"), updated_topic_lines))
159+
160+
self.assertTrue(
161+
start_test_scope_lines[0].endswith(
162+
" This is provided by the user" + os.linesep),
163+
"User provided content was modified")
164+
165+
def test_that_we_dont_override_user_text_in_sections(self):
166+
"""
167+
Checks that when we don't change user written text in section when
168+
updating the topic.
169+
"""
170+
topic_file_path = TEST_INPUTS / "user_content_heading_topic.md"
171+
with open(topic_file_path, "r") as topic_file:
172+
updated_topic_lines = self.test_skeleton.update_topic_meta_text(
173+
topic_file)
174+
175+
start_test_scope_lines = list(
176+
dropwhile(
177+
lambda line: not line.startswith(
178+
"Users can add different content here"),
179+
updated_topic_lines))
180+
181+
self.assertTrue(
182+
start_test_scope_lines[0].startswith(
183+
"Users can add different content here."),
184+
"User provided content was modified")
185+
self.assertTrue(start_test_scope_lines[1].startswith("<table>"),
186+
"User provided content was modified")
187+
self.assertTrue(start_test_scope_lines[2].startswith("</table>"),
188+
"User provided content was modified")
189+
190+
@mock.patch('topic_updater._cli_yn_choice')
191+
def test_if_missing_section_gets_added_to_the_end(self, mock_cli_yn):
192+
"""
193+
Checks if a section that is missing at the end of the topic file gets
194+
automatically added.
195+
"""
196+
mock_cli_yn.return_value = True
197+
topic_file_path = TEST_INPUTS / "missing_sections.md"
198+
with open(topic_file_path, "r") as topic_file:
199+
updated_topic_lines = self.test_skeleton.update_topic_meta_text(
200+
topic_file)
201+
202+
self.assertEqual(
203+
updated_topic_lines[-3].rstrip(), "## Missing end section",
204+
"Missing section was not added to the end of the file.")
205+
self.assertEqual(
206+
updated_topic_lines[-1].rstrip(),
207+
"_ This section could be missing at the end of the document _")
208+
209+
@mock.patch('topic_updater._cli_yn_choice')
210+
def test_if_missing_section_gets_added_in_the_middle(self, mock_cli_yn):
211+
"""
212+
Checks if a section that is missing in the middle of the topic file
213+
gets added if the user wants it. The test assumes the user supplies
214+
yes as an answer.
215+
"""
216+
mock_cli_yn.return_value = True
217+
topic_file_path = TEST_INPUTS / "missing_sections.md"
218+
with open(topic_file_path, "r") as topic_file:
219+
updated_topic_lines = self.test_skeleton.update_topic_meta_text(
220+
topic_file)
221+
222+
# Reduces the topic lines to only contain sections and removes all
223+
# lines before the test scope, i.e., the section before the missing
224+
# section.
225+
start_test_scope_lines = list(
226+
filter(
227+
lambda line: line.startswith("##"),
228+
dropwhile(
229+
lambda line: not line.startswith(
230+
"## Section with user content"),
231+
iter(updated_topic_lines))))
232+
233+
# Verify that the previous section is correct
234+
self.assertTrue(
235+
start_test_scope_lines[0].startswith(
236+
"## Section with user content"),
237+
"The section before the added missing section is wrong.")
238+
239+
# Verify the section was inserted
240+
self.assertEqual(
241+
start_test_scope_lines[1].rstrip(), "## Missing mid section",
242+
"The missing section was not inserted correctly.")
243+
244+
# Verify the next section is correct
245+
self.assertTrue(
246+
start_test_scope_lines[2].startswith(
247+
"## Italics text should be updated"),
248+
"The section after the added missing section is wrong.")
249+
250+
def test_that_meta_text_gets_updated(self):
251+
"""
252+
Checks that meta text in the topic gets updated according to the
253+
skeleton.
254+
"""
255+
topic_file_path = TEST_INPUTS / "fix_wrong_sections.md"
256+
with open(topic_file_path, "r") as topic_file:
257+
updated_topic_lines = self.test_skeleton.update_topic_meta_text(
258+
topic_file)
259+
260+
topic_lines_starting_from_italics_section = list(
261+
dropwhile(
262+
lambda line: not line.startswith(
263+
"## Italics text should be updated"),
264+
iter(updated_topic_lines)))
265+
self.assertEqual(
266+
topic_lines_starting_from_italics_section[0].rstrip(),
267+
"## Italics text should be updated",
268+
"Could not find italics section.")
269+
self.assertEqual(
270+
topic_lines_starting_from_italics_section[2].rstrip(),
271+
"_ Updated italics text. _")
272+
273+
def test_topic_does_not_end_in_empty_line(self):
274+
"""
275+
Checks that the update topic lines do not end with and empty line.
276+
"""
277+
topic_file_path = TEST_INPUTS / "user_content_heading_topic.md"
278+
with open(topic_file_path, "r") as topic_file:
279+
updated_topic_lines = self.test_skeleton.update_topic_meta_text(
280+
topic_file)
281+
282+
self.assertNotEqual(updated_topic_lines[-1], os.linesep)
283+
284+
def test_newline_between_heading_and_meta_text(self):
285+
"""
286+
Checks that we emit a newline between the heading and the meta text.
287+
"""
288+
topic_file_path = TEST_INPUTS / "user_content_heading_topic.md"
289+
with open(topic_file_path, "r") as topic_file:
290+
updated_topic_lines = self.test_skeleton.update_topic_meta_text(
291+
topic_file)
292+
293+
start_test_scope_lines = list(
294+
dropwhile(
295+
lambda line: not line.startswith("## Section with user"),
296+
updated_topic_lines))
297+
self.assertEqual(start_test_scope_lines[1], os.linesep,
298+
"No newline between heading and meta text.")
299+
self.assertTrue(
300+
start_test_scope_lines[2].startswith("_ Example section"))

0 commit comments

Comments
 (0)