Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c2564f9

Browse files
committed
Issue #18425: Unittests for idlelib.IdleHistory. First patch by R. Jayakrishnan.
1 parent 5e4d639 commit c2564f9

2 files changed

Lines changed: 179 additions & 3 deletions

File tree

Lib/idlelib/IdleHistory.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,13 @@ def _put_source(self, where, source):
4949
self.text.insert(where, output)
5050

5151
def fetch(self, reverse):
52-
"Fetch statememt and enter into text at cursor."
52+
'''Fetch statememt and replace current line in text widget.
53+
54+
Set prefix and pointer as needed for successive fetches.
55+
Reset them to None, None when returning to the start line.
56+
Sound bell when return to start line or cannot leave a line
57+
because cyclic is False.
58+
'''
5359
nhist = len(self.history)
5460
pointer = self.pointer
5561
prefix = self.prefix
@@ -64,7 +70,7 @@ def fetch(self, reverse):
6470
else:
6571
if self.cyclic:
6672
pointer = -1 # will be incremented
67-
else:
73+
else: # abort history_next
6874
self.text.bell()
6975
return
7076
nprefix = len(prefix)
@@ -75,7 +81,7 @@ def fetch(self, reverse):
7581
pointer = pointer + 1
7682
if pointer < 0 or pointer >= nhist:
7783
self.text.bell()
78-
if not self.cyclic and pointer < 0:
84+
if not self.cyclic and pointer < 0: # abort history_prev
7985
return
8086
else:
8187
if self._get_source("iomark", "end-1c") != prefix:
@@ -106,3 +112,9 @@ def store(self, source):
106112
self.history.append(source)
107113
self.pointer = None
108114
self.prefix = None
115+
116+
if __name__ == "__main__":
117+
from test import support
118+
support.use_resources = ['gui']
119+
from unittest import main
120+
main('idlelib.idle_test.test_idlehistory', verbosity=2, exit=False)
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import unittest
2+
from test.support import requires
3+
4+
import tkinter as tk
5+
from tkinter import Text as tkText
6+
from idlelib.idle_test.mock_tk import Text as mkText
7+
from idlelib.IdleHistory import History
8+
from idlelib.configHandler import idleConf
9+
10+
line1 = 'a = 7'
11+
line2 = 'b = a'
12+
13+
class StoreTest(unittest.TestCase):
14+
'''Tests History.__init__ and History.store with mock Text'''
15+
16+
@classmethod
17+
def setUpClass(cls):
18+
cls.text = mkText()
19+
cls.history = History(cls.text)
20+
21+
def tearDown(self):
22+
self.text.delete('1.0', 'end')
23+
self.history.history = []
24+
25+
def test_init(self):
26+
self.assertIs(self.history.text, self.text)
27+
self.assertEqual(self.history.history, [])
28+
self.assertIsNone(self.history.prefix)
29+
self.assertIsNone(self.history.pointer)
30+
self.assertEqual(self.history.cyclic,
31+
idleConf.GetOption("main", "History", "cyclic", 1, "bool"))
32+
33+
def test_store_short(self):
34+
self.history.store('a')
35+
self.assertEqual(self.history.history, [])
36+
self.history.store(' a ')
37+
self.assertEqual(self.history.history, [])
38+
39+
def test_store_dup(self):
40+
self.history.store(line1)
41+
self.assertEqual(self.history.history, [line1])
42+
self.history.store(line2)
43+
self.assertEqual(self.history.history, [line1, line2])
44+
self.history.store(line1)
45+
self.assertEqual(self.history.history, [line2, line1])
46+
47+
def test_store_reset(self):
48+
self.history.prefix = line1
49+
self.history.pointer = 0
50+
self.history.store(line2)
51+
self.assertIsNone(self.history.prefix)
52+
self.assertIsNone(self.history.pointer)
53+
54+
55+
class TextWrapper:
56+
def __init__(self, master):
57+
self.text = tkText(master=master)
58+
self._bell = False
59+
def __getattr__(self, name):
60+
return getattr(self.text, name)
61+
def bell(self):
62+
self._bell = True
63+
64+
class FetchTest(unittest.TestCase):
65+
'''Test History.fetch with wrapped tk.Text.
66+
'''
67+
@classmethod
68+
def setUpClass(cls):
69+
requires('gui')
70+
cls.root = tk.Tk()
71+
72+
def setUp(self):
73+
self.text = text = TextWrapper(self.root)
74+
text.insert('1.0', ">>> ")
75+
text.mark_set('iomark', '1.4')
76+
text.mark_gravity('iomark', 'left')
77+
self.history = History(text)
78+
self.history.history = [line1, line2]
79+
80+
@classmethod
81+
def tearDownClass(cls):
82+
cls.root.destroy()
83+
84+
def fetch_test(self, reverse, line, prefix, index, *, bell=False):
85+
# Perform one fetch as invoked by Alt-N or Alt-P
86+
# Test the result. The line test is the most important.
87+
# The last two are diagnostic of fetch internals.
88+
History = self.history
89+
History.fetch(reverse)
90+
Equal = self.assertEqual
91+
Equal(self.text.get('iomark', 'end-1c'), line)
92+
Equal(self.text._bell, bell)
93+
if bell:
94+
self.text._bell = False
95+
Equal(History.prefix, prefix)
96+
Equal(History.pointer, index)
97+
98+
def test_fetch_prev_cyclic(self):
99+
prefix = ''
100+
test = self.fetch_test
101+
test(True, line2, prefix, 1)
102+
test(True, line1, prefix, 0)
103+
test(True, prefix, None, None, bell=True)
104+
105+
def test_fetch_next_cyclic(self):
106+
prefix = ''
107+
test = self.fetch_test
108+
test(False, line1, prefix, 0)
109+
test(False, line2, prefix, 1)
110+
test(False, prefix, None, None, bell=True)
111+
112+
# Prefix 'a' tests skip line2, which starts with 'b'
113+
def test_fetch_prev_prefix(self):
114+
prefix = 'a'
115+
self.text.insert('iomark', prefix)
116+
self.fetch_test(True, line1, prefix, 0)
117+
self.fetch_test(True, prefix, None, None, bell=True)
118+
119+
def test_fetch_next_prefix(self):
120+
prefix = 'a'
121+
self.text.insert('iomark', prefix)
122+
self.fetch_test(False, line1, prefix, 0)
123+
self.fetch_test(False, prefix, None, None, bell=True)
124+
125+
def test_fetch_prev_noncyclic(self):
126+
prefix = ''
127+
self.history.cyclic = False
128+
test = self.fetch_test
129+
test(True, line2, prefix, 1)
130+
test(True, line1, prefix, 0)
131+
test(True, line1, prefix, 0, bell=True)
132+
133+
def test_fetch_next_noncyclic(self):
134+
prefix = ''
135+
self.history.cyclic = False
136+
test = self.fetch_test
137+
test(False, prefix, None, None, bell=True)
138+
test(True, line2, prefix, 1)
139+
test(False, prefix, None, None, bell=True)
140+
test(False, prefix, None, None, bell=True)
141+
142+
def test_fetch_cursor_move(self):
143+
# Move cursor after fetch
144+
self.history.fetch(reverse=True) # initialization
145+
self.text.mark_set('insert', 'iomark')
146+
self.fetch_test(True, line2, None, None, bell=True)
147+
148+
def test_fetch_edit(self):
149+
# Edit after fetch
150+
self.history.fetch(reverse=True) # initialization
151+
self.text.delete('iomark', 'insert', )
152+
self.text.insert('iomark', 'a =')
153+
self.fetch_test(True, line1, 'a =', 0) # prefix is reset
154+
155+
def test_history_prev_next(self):
156+
# Minimally test functions bound to events
157+
self.history.history_prev('dummy event')
158+
self.assertEqual(self.history.pointer, 1)
159+
self.history.history_next('dummy event')
160+
self.assertEqual(self.history.pointer, None)
161+
162+
163+
if __name__ == '__main__':
164+
unittest.main(verbosity=2, exit=2)

0 commit comments

Comments
 (0)