1- # .. Copyright (C) 2017 Bryan A. Jones.
2- #
3- # This file is part of E-Book Binder.
4- #
5- # E-Book Binder is free software: you can redistribute it and/or modify it
6- # under the terms of the GNU General Public License as published by the Free
7- # Software Foundation, either version 3 of the License, or (at your option)
8- # any later version.
9- #
10- # E-Book Binder is distributed in the hope that it will be useful, but WITHOUT
11- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12- # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13- # details.
14- #
15- # You should have received a copy of the GNU General Public License along
16- # with E-Book Binder. If not, see <http://www.gnu.org/licenses/>.
17- #
18- # .. highlight:: python
19- #
201# ***********************
212# test_lp.py - Unit tests
223# ***********************
234# Require Python 3 to run tests.
24- import sys
25- from unittest import TestCase , skip
26- if sys .version_info < (3 , 3 ):
27- class TestOldPython (TestCase ):
28- @skip ('Tests require Python 3.' )
29- def test_1 ():
30- pass
31- else :
32- #
33- # Imports
34- # =======
35- # These are listed in the order prescribed by `PEP 8
36- # <http://www.python.org/dev/peps/pep-0008/#imports>`_.
37- #
38- # Standard library
39- # ----------------
40- from pathlib import Path
41- from time import sleep
42- #
43- # Third-party imports
44- # -------------------
45- from selenium .webdriver .common .by import By
46- from selenium .webdriver .support .ui import WebDriverWait
47- from selenium .webdriver .support import expected_conditions as EC
48- #
49- # Local imports
50- # -------------
51- from runestone .lp .lp import (
52- _remove_code_solutions , _textarea_replacement ,
53- TEXTAREA_REPLACEMENT_STRING , _source_read
54- )
55- from runestone .server .lp_common_lib import _add_line_comment_delimiter , STUDENT_SOURCE_PATH , read_sphinx_config , SPHINX_CONFIG_NAME
56- from runestone .unittest_base import module_fixture_maker , RunestoneTestCase
57-
58- mf , setUpModule , tearDownModule = module_fixture_maker (__file__ , True )
59- #
60- # Mock classes
61- # ============
62- class MockApp :
63- def __init__ (self , docname ):
64- self .builder = MockBuilder (docname )
65- self .env = self .builder .env
66- self .outdir = '_build/html'
67-
68- class MockBuilder :
69- def __init__ (self , docname ):
70- self .env = MockEnv (docname )
71-
72- class MockEnv :
73- def __init__ (self , docname ):
74- self .docname = docname
75- self .srcdir = '_source'
76- self .titles = {docname : 'A test file' }
77-
78- def doc2path (self , docname , * args ):
79- return docname
80- #
81- # Supporting utilities
82- # ====================
83- # Set up Sphinx mocks.
84- def sphinx_setup ():
85- app = MockApp ('test.c' )
86- env = app .builder .env
87- return app , env
88- #
89- # Tests
90- # =====
91- # Test the code solution removal.
92- class Unit_Test_Lp (TestCase ):
93- # Make sure there were no unexpected warnings in the build.
94- def test_1 (self ):
95- self .assertEqual (mf .build_stderr_data .count ('WARNING' ), 1 )
96-
97- # Make sure that the student source files were generated.
98- def test_1a (self ):
99- sphinx_config = read_sphinx_config ()
100- sphinx_source_path = sphinx_config ['SPHINX_SOURCE_PATH' ]
101- sphinx_out_path = sphinx_config ['SPHINX_OUT_PATH' ]
102- self .assertTrue (sphinx_source_path )
103-
104- # Check that a HTML version of the source was produced.
105- self .assertTrue ((Path (sphinx_out_path ) / 'lp_tester.s-source.html' ).exists ())
106-
107- # Check that the student source has answers removed.
108- with open (str (Path (sphinx_out_path ) / STUDENT_SOURCE_PATH / 'lp_tester.s' ), encoding = 'utf-8' ) as f :
109- student_source = f .read ()
110- self .assertNotIn ('_u16_b: .space 2' , student_source )
111- self .assertNotIn ('mov #0xA15F, W0' , student_source )
112-
113- # Test _remove_code_solutions.
114- def test_2 (self ):
115- # Note: to avoid the tags being recognized when this file is parsed by Sphinx, they're broken apart in the strings below.
116- self .assertEqual (_remove_code_solutions ('foo.s' , """# line 1
5+
6+ #
7+ # Imports
8+ # =======
9+ # These are listed in the order prescribed by `PEP 8
10+ # <http://www.python.org/dev/peps/pep-0008/#imports>`_.
11+ #
12+ # Standard library
13+ # ----------------
14+ from pathlib import Path
15+ from time import sleep
16+ from unittest import TestCase
17+ #
18+ # Third-party imports
19+ # -------------------
20+ from selenium .webdriver .common .by import By
21+ from selenium .webdriver .support .ui import WebDriverWait
22+ from selenium .webdriver .support import expected_conditions as EC
23+ #
24+ # Local imports
25+ # -------------
26+ from runestone .lp .lp import (
27+ _remove_code_solutions , _textarea_replacement ,
28+ TEXTAREA_REPLACEMENT_STRING , _source_read
29+ )
30+ from runestone .lp .lp_common_lib import _add_line_comment_delimiter , STUDENT_SOURCE_PATH , read_sphinx_config
31+ from runestone .unittest_base import module_fixture_maker , RunestoneTestCase
32+
33+ mf , setUpModule , tearDownModule = module_fixture_maker (__file__ , True )
34+
35+
36+ # Mock classes
37+ # ============
38+ class MockApp :
39+ def __init__ (self , docname ):
40+ self .builder = MockBuilder (docname )
41+ self .env = self .builder .env
42+ self .outdir = '_build/html'
43+
44+
45+ class MockBuilder :
46+ def __init__ (self , docname ):
47+ self .env = MockEnv (docname )
48+
49+
50+ class MockEnv :
51+ def __init__ (self , docname ):
52+ self .docname = docname
53+ self .srcdir = '_source'
54+ self .titles = {docname : 'A test file' }
55+
56+ def doc2path (self , docname , * args ):
57+ return docname
58+
59+
60+ # Supporting utilities
61+ # ====================
62+ # Set up Sphinx mocks.
63+ def sphinx_setup ():
64+ app = MockApp ('test.c' )
65+ env = app .builder .env
66+ return app , env
67+
68+
69+ # Tests
70+ # =====
71+ # Test the code solution removal.
72+ class Unit_Test_Lp (TestCase ):
73+ # Make sure there were no unexpected warnings in the build.
74+ def test_1 (self ):
75+ self .assertEqual (mf .build_stderr_data .count ('WARNING' ), 1 )
76+
77+ # Make sure that the student source files were generated.
78+ def test_1a (self ):
79+ sphinx_config = read_sphinx_config ()
80+ sphinx_source_path = sphinx_config ['SPHINX_SOURCE_PATH' ]
81+ sphinx_out_path = sphinx_config ['SPHINX_OUT_PATH' ]
82+ self .assertTrue (sphinx_source_path )
83+
84+ # Check that a HTML version of the source was produced.
85+ self .assertTrue ((Path (sphinx_out_path ) / 'lp_tester.s-source.html' ).exists ())
86+
87+ # Check that the student source has answers removed.
88+ with open (str (Path (sphinx_out_path ) / STUDENT_SOURCE_PATH / 'lp_tester.s' ), encoding = 'utf-8' ) as f :
89+ student_source = f .read ()
90+ self .assertNotIn ('_u16_b: .space 2' , student_source )
91+ self .assertNotIn ('mov #0xA15F, W0' , student_source )
92+
93+ # Test _remove_code_solutions.
94+ def test_2 (self ):
95+ # Note: to avoid the tags being recognized when this file is parsed by Sphinx, they're broken apart in the strings below.
96+ self .assertEqual (_remove_code_solutions ('foo.s' , """# line 1
11797# line 2
11898# line 3
11999# SOLUTION_""" """BEGIN
@@ -137,23 +117,22 @@ def test_2(self):
137117# Snip 14
138118# line 15""" )
139119
140- # Test the addition of comments to a string.
141- def test_3 (self ):
142- self .assertEqual (_add_line_comment_delimiter ('1\n 2' , 'foo.py' ), '# 1\n # 2' )
143- self .assertEqual (_add_line_comment_delimiter ('1\n 2' , 'foo.c' ), '// 1\n // 2' )
120+ # Test the addition of comments to a string.
121+ def test_3 (self ):
122+ self .assertEqual (_add_line_comment_delimiter ('1\n 2' , 'foo.py' ), '# 1\n # 2' )
123+ self .assertEqual (_add_line_comment_delimiter ('1\n 2' , 'foo.c' ), '// 1\n // 2' )
144124
145- # Test ``_textarea_replacement``.
146- def test_4 (self ):
147- # Check a mimimum-length replacement.
148- self .assertEqual (_textarea_replacement (3 , 4 , 'foo.py' ), TEXTAREA_REPLACEMENT_STRING .format (4 ))
125+ # Test ``_textarea_replacement``.
126+ def test_4 (self ):
127+ # Check a mimimum-length replacement.
128+ self .assertEqual (_textarea_replacement (3 , 4 , 'foo.py' ), TEXTAREA_REPLACEMENT_STRING .format (4 ))
149129
150- # Check a replcement with added lines.
151- self .assertEqual (_textarea_replacement (3 , 22 , 'foo.py' ).count ('\n ' ), 20 )
130+ # Check a replcement with added lines.
131+ self .assertEqual (_textarea_replacement (3 , 22 , 'foo.py' ).count ('\n ' ), 20 )
152132
153- # Test the source-read event callback.
154- def test_5 (self ):
155- src = [
156- """Line 1
133+ # Test the source-read event callback.
134+ def test_5 (self ):
135+ src = ["""Line 1
157136Line 2
158137SOLUTION_""" """BEGIN
159138Line 4
@@ -165,11 +144,9 @@ def test_5(self):
165144Line 10
166145SOLUTION_""" """END
167146Line 12""" ]
168- app , env = sphinx_setup ()
169- _source_read (app , env .docname , src )
170- self .assertEqual (src ,
171- [
172- """Line 1
147+ app , env = sphinx_setup ()
148+ _source_read (app , env .docname , src )
149+ self .assertEqual (src , ["""Line 1
173150Line 2
174151
175152.. raw::
@@ -182,25 +159,26 @@ def test_5(self):
182159
183160Line 12""" ])
184161
185- class Functional_Test_Lp (RunestoneTestCase ):
186- def test_1 (self ):
187- self .driver .get (self .host + "/lp_tester.s.html" )
188- snippets = self .driver .find_elements_by_class_name ("code_snippet" )
189- self .assertEqual (len (snippets ), 2 )
190- check_button = self .driver .find_element_by_id ('e1' )
191- result_area = self .driver .find_element_by_id ('lp-result' )
192-
193- # Set snippets.
194- self .driver .execute_script ('LPList["e1"].textAreas[0].setValue("xxx"); LPList["e1"].textAreas[1].setValue("yyy");' )
195- self .assertFalse (result_area .text )
196-
197- # Click the test button.
198- check_button .click ()
199- WebDriverWait (self .driver , 10 ).until (EC .text_to_be_present_in_element_value ((By .ID , 'lp-result' ), 'Building...' ))
200-
201- # Refresh the page. See if saved snippets are restored.
202- self .driver .get (self .host + "/lp_tester.s.html" )
203- # Wait for script to run. I don't see a wait condition what would work, unfortunately.
204- sleep (0.5 )
205- self .assertEqual (self .driver .execute_script ('return LPList["e1"].textAreas[0].getValue();' ), 'xxx' )
206- self .assertEqual (self .driver .execute_script ('return LPList["e1"].textAreas[1].getValue();' ), 'yyy' )
162+
163+ class Functional_Test_Lp (RunestoneTestCase ):
164+ def test_1 (self ):
165+ self .driver .get (self .host + "/lp_tester.s.html" )
166+ snippets = self .driver .find_elements_by_class_name ("code_snippet" )
167+ self .assertEqual (len (snippets ), 2 )
168+ check_button = self .driver .find_element_by_id ('e1' )
169+ result_area = self .driver .find_element_by_id ('lp-result' )
170+
171+ # Set snippets.
172+ self .driver .execute_script ('LPList["e1"].textAreas[0].setValue("xxx"); LPList["e1"].textAreas[1].setValue("yyy");' )
173+ self .assertFalse (result_area .text )
174+
175+ # Click the test button.
176+ check_button .click ()
177+ WebDriverWait (self .driver , 10 ).until (EC .text_to_be_present_in_element_value ((By .ID , 'lp-result' ), 'Building...' ))
178+
179+ # Refresh the page. See if saved snippets are restored.
180+ self .driver .get (self .host + "/lp_tester.s.html" )
181+ # Wait for script to run. I don't see a wait condition what would work, unfortunately.
182+ sleep (0.5 )
183+ self .assertEqual (self .driver .execute_script ('return LPList["e1"].textAreas[0].getValue();' ), 'xxx' )
184+ self .assertEqual (self .driver .execute_script ('return LPList["e1"].textAreas[1].getValue();' ), 'yyy' )
0 commit comments