From ea3dc8029ab6a0f1ee6a8a72f1612dea74892e08 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Mon, 18 Jun 2018 04:47:59 -0400 Subject: bpo-33855: More edits and new minimal tests for IDLE (GH-7761) Part 2 of 3. Continues PR #7689, changeset ee5ef30. Edit and add tests for 18 modules, help_about to replace and run. --- Lib/idlelib/help_about.py | 5 +- Lib/idlelib/hyperparser.py | 4 +- Lib/idlelib/idle_test/test_help_about.py | 17 +- Lib/idlelib/idle_test/test_history.py | 6 +- Lib/idlelib/idle_test/test_hyperparser.py | 6 +- Lib/idlelib/idle_test/test_iomenu.py | 261 ++++-------------------------- Lib/idlelib/idle_test/test_macosx.py | 6 +- Lib/idlelib/idle_test/test_mainmenu.py | 21 +++ Lib/idlelib/idle_test/test_multicall.py | 40 +++++ Lib/idlelib/idle_test/test_outwin.py | 7 +- Lib/idlelib/idle_test/test_paragraph.py | 47 +++--- Lib/idlelib/idle_test/test_parenmatch.py | 4 +- Lib/idlelib/idle_test/test_pathbrowser.py | 12 +- Lib/idlelib/idle_test/test_percolator.py | 8 +- Lib/idlelib/idle_test/test_pyparse.py | 9 +- Lib/idlelib/idle_test/test_pyshell.py | 42 +++++ Lib/idlelib/idle_test/test_query.py | 12 +- Lib/idlelib/idle_test/test_redirector.py | 10 +- Lib/idlelib/idle_test/test_replace.py | 9 +- Lib/idlelib/idle_test/test_run.py | 237 ++++++++++++++++++++++++++- Lib/idlelib/iomenu.py | 4 +- Lib/idlelib/mainmenu.py | 17 +- Lib/idlelib/multicall.py | 3 + Lib/idlelib/paragraph.py | 5 +- Lib/idlelib/parenmatch.py | 4 +- Lib/idlelib/percolator.py | 5 +- Lib/idlelib/pyparse.py | 6 +- Lib/idlelib/query.py | 4 +- Lib/idlelib/redirector.py | 5 +- Lib/idlelib/replace.py | 5 +- 30 files changed, 483 insertions(+), 338 deletions(-) create mode 100644 Lib/idlelib/idle_test/test_mainmenu.py create mode 100644 Lib/idlelib/idle_test/test_multicall.py create mode 100644 Lib/idlelib/idle_test/test_pyshell.py diff --git a/Lib/idlelib/help_about.py b/Lib/idlelib/help_about.py index 77b4b18..2a274a9 100644 --- a/Lib/idlelib/help_about.py +++ b/Lib/idlelib/help_about.py @@ -199,7 +199,8 @@ class AboutDialog(Toplevel): if __name__ == '__main__': - import unittest - unittest.main('idlelib.idle_test.test_help_about', verbosity=2, exit=False) + from unittest import main + main('idlelib.idle_test.test_help_about', verbosity=2, exit=False) + from idlelib.idle_test.htest import run run(AboutDialog) diff --git a/Lib/idlelib/hyperparser.py b/Lib/idlelib/hyperparser.py index a42665b..7581fe27 100644 --- a/Lib/idlelib/hyperparser.py +++ b/Lib/idlelib/hyperparser.py @@ -308,5 +308,5 @@ class HyperParser: if __name__ == '__main__': - import unittest - unittest.main('idlelib.idle_test.test_hyperparser', verbosity=2) + from unittest import main + main('idlelib.idle_test.test_hyperparser', verbosity=2) diff --git a/Lib/idlelib/idle_test/test_help_about.py b/Lib/idlelib/idle_test/test_help_about.py index 9c6a834..5839b5d 100644 --- a/Lib/idlelib/idle_test/test_help_about.py +++ b/Lib/idlelib/idle_test/test_help_about.py @@ -1,18 +1,19 @@ -'''Test idlelib.help_about. +"""Test help_about, coverage 100%. +help_about.build_bits branches on sys.platform='darwin'. +'100% combines coverage on Mac and others. +""" -Coverage: 100% -''' +from idlelib import help_about +import unittest from test.support import requires, findfile from tkinter import Tk, TclError -import unittest -from unittest import mock from idlelib.idle_test.mock_idle import Func from idlelib.idle_test.mock_tk import Mbox_func -from idlelib.help_about import AboutDialog as About -from idlelib import help_about from idlelib import textview import os.path -from platform import python_version, architecture +from platform import python_version + +About = help_about.AboutDialog class LiveDialogTest(unittest.TestCase): diff --git a/Lib/idlelib/idle_test/test_history.py b/Lib/idlelib/idle_test/test_history.py index b278010..6753965 100644 --- a/Lib/idlelib/idle_test/test_history.py +++ b/Lib/idlelib/idle_test/test_history.py @@ -1,15 +1,18 @@ +" Test history, coverage 100%." + +from idlelib.history import History import unittest from test.support import requires import tkinter as tk from tkinter import Text as tkText from idlelib.idle_test.mock_tk import Text as mkText -from idlelib.history import History from idlelib.config import idleConf line1 = 'a = 7' line2 = 'b = a' + class StoreTest(unittest.TestCase): '''Tests History.__init__ and History.store with mock Text''' @@ -61,6 +64,7 @@ class TextWrapper: def bell(self): self._bell = True + class FetchTest(unittest.TestCase): '''Test History.fetch with wrapped tk.Text. ''' diff --git a/Lib/idlelib/idle_test/test_hyperparser.py b/Lib/idlelib/idle_test/test_hyperparser.py index 73c8281..8dbfc63 100644 --- a/Lib/idlelib/idle_test/test_hyperparser.py +++ b/Lib/idlelib/idle_test/test_hyperparser.py @@ -1,9 +1,10 @@ -"""Unittest for idlelib.hyperparser.py.""" +"Test hyperparser, coverage 98%." + +from idlelib.hyperparser import HyperParser import unittest from test.support import requires from tkinter import Tk, Text from idlelib.editor import EditorWindow -from idlelib.hyperparser import HyperParser class DummyEditwin: def __init__(self, text): @@ -270,5 +271,6 @@ class HyperParserTest(unittest.TestCase): self.assertEqual(eat_id('2' + 'a' * (length - 1), 0, length), 0) self.assertEqual(eat_id('2' + 'é' * (length - 1), 0, length), 0) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_iomenu.py b/Lib/idlelib/idle_test/test_iomenu.py index 65bf593..743a05b 100644 --- a/Lib/idlelib/idle_test/test_iomenu.py +++ b/Lib/idlelib/idle_test/test_iomenu.py @@ -1,233 +1,36 @@ -import unittest -import io - -from idlelib.run import PseudoInputFile, PseudoOutputFile - - -class S(str): - def __str__(self): - return '%s:str' % type(self).__name__ - def __unicode__(self): - return '%s:unicode' % type(self).__name__ - def __len__(self): - return 3 - def __iter__(self): - return iter('abc') - def __getitem__(self, *args): - return '%s:item' % type(self).__name__ - def __getslice__(self, *args): - return '%s:slice' % type(self).__name__ - -class MockShell: - def __init__(self): - self.reset() - - def write(self, *args): - self.written.append(args) - - def readline(self): - return self.lines.pop() - - def close(self): - pass - - def reset(self): - self.written = [] - - def push(self, lines): - self.lines = list(lines)[::-1] - - -class PseudeOutputFilesTest(unittest.TestCase): - def test_misc(self): - shell = MockShell() - f = PseudoOutputFile(shell, 'stdout', 'utf-8') - self.assertIsInstance(f, io.TextIOBase) - self.assertEqual(f.encoding, 'utf-8') - self.assertIsNone(f.errors) - self.assertIsNone(f.newlines) - self.assertEqual(f.name, '') - self.assertFalse(f.closed) - self.assertTrue(f.isatty()) - self.assertFalse(f.readable()) - self.assertTrue(f.writable()) - self.assertFalse(f.seekable()) - - def test_unsupported(self): - shell = MockShell() - f = PseudoOutputFile(shell, 'stdout', 'utf-8') - self.assertRaises(OSError, f.fileno) - self.assertRaises(OSError, f.tell) - self.assertRaises(OSError, f.seek, 0) - self.assertRaises(OSError, f.read, 0) - self.assertRaises(OSError, f.readline, 0) - - def test_write(self): - shell = MockShell() - f = PseudoOutputFile(shell, 'stdout', 'utf-8') - f.write('test') - self.assertEqual(shell.written, [('test', 'stdout')]) - shell.reset() - f.write('t\xe8st') - self.assertEqual(shell.written, [('t\xe8st', 'stdout')]) - shell.reset() - - f.write(S('t\xe8st')) - self.assertEqual(shell.written, [('t\xe8st', 'stdout')]) - self.assertEqual(type(shell.written[0][0]), str) - shell.reset() +"Test , coverage 16%." - self.assertRaises(TypeError, f.write) - self.assertEqual(shell.written, []) - self.assertRaises(TypeError, f.write, b'test') - self.assertRaises(TypeError, f.write, 123) - self.assertEqual(shell.written, []) - self.assertRaises(TypeError, f.write, 'test', 'spam') - self.assertEqual(shell.written, []) - - def test_writelines(self): - shell = MockShell() - f = PseudoOutputFile(shell, 'stdout', 'utf-8') - f.writelines([]) - self.assertEqual(shell.written, []) - shell.reset() - f.writelines(['one\n', 'two']) - self.assertEqual(shell.written, - [('one\n', 'stdout'), ('two', 'stdout')]) - shell.reset() - f.writelines(['on\xe8\n', 'tw\xf2']) - self.assertEqual(shell.written, - [('on\xe8\n', 'stdout'), ('tw\xf2', 'stdout')]) - shell.reset() - - f.writelines([S('t\xe8st')]) - self.assertEqual(shell.written, [('t\xe8st', 'stdout')]) - self.assertEqual(type(shell.written[0][0]), str) - shell.reset() - - self.assertRaises(TypeError, f.writelines) - self.assertEqual(shell.written, []) - self.assertRaises(TypeError, f.writelines, 123) - self.assertEqual(shell.written, []) - self.assertRaises(TypeError, f.writelines, [b'test']) - self.assertRaises(TypeError, f.writelines, [123]) - self.assertEqual(shell.written, []) - self.assertRaises(TypeError, f.writelines, [], []) - self.assertEqual(shell.written, []) - - def test_close(self): - shell = MockShell() - f = PseudoOutputFile(shell, 'stdout', 'utf-8') - self.assertFalse(f.closed) - f.write('test') - f.close() - self.assertTrue(f.closed) - self.assertRaises(ValueError, f.write, 'x') - self.assertEqual(shell.written, [('test', 'stdout')]) - f.close() - self.assertRaises(TypeError, f.close, 1) - - -class PseudeInputFilesTest(unittest.TestCase): - def test_misc(self): - shell = MockShell() - f = PseudoInputFile(shell, 'stdin', 'utf-8') - self.assertIsInstance(f, io.TextIOBase) - self.assertEqual(f.encoding, 'utf-8') - self.assertIsNone(f.errors) - self.assertIsNone(f.newlines) - self.assertEqual(f.name, '') - self.assertFalse(f.closed) - self.assertTrue(f.isatty()) - self.assertTrue(f.readable()) - self.assertFalse(f.writable()) - self.assertFalse(f.seekable()) - - def test_unsupported(self): - shell = MockShell() - f = PseudoInputFile(shell, 'stdin', 'utf-8') - self.assertRaises(OSError, f.fileno) - self.assertRaises(OSError, f.tell) - self.assertRaises(OSError, f.seek, 0) - self.assertRaises(OSError, f.write, 'x') - self.assertRaises(OSError, f.writelines, ['x']) - - def test_read(self): - shell = MockShell() - f = PseudoInputFile(shell, 'stdin', 'utf-8') - shell.push(['one\n', 'two\n', '']) - self.assertEqual(f.read(), 'one\ntwo\n') - shell.push(['one\n', 'two\n', '']) - self.assertEqual(f.read(-1), 'one\ntwo\n') - shell.push(['one\n', 'two\n', '']) - self.assertEqual(f.read(None), 'one\ntwo\n') - shell.push(['one\n', 'two\n', 'three\n', '']) - self.assertEqual(f.read(2), 'on') - self.assertEqual(f.read(3), 'e\nt') - self.assertEqual(f.read(10), 'wo\nthree\n') - - shell.push(['one\n', 'two\n']) - self.assertEqual(f.read(0), '') - self.assertRaises(TypeError, f.read, 1.5) - self.assertRaises(TypeError, f.read, '1') - self.assertRaises(TypeError, f.read, 1, 1) - - def test_readline(self): - shell = MockShell() - f = PseudoInputFile(shell, 'stdin', 'utf-8') - shell.push(['one\n', 'two\n', 'three\n', 'four\n']) - self.assertEqual(f.readline(), 'one\n') - self.assertEqual(f.readline(-1), 'two\n') - self.assertEqual(f.readline(None), 'three\n') - shell.push(['one\ntwo\n']) - self.assertEqual(f.readline(), 'one\n') - self.assertEqual(f.readline(), 'two\n') - shell.push(['one', 'two', 'three']) - self.assertEqual(f.readline(), 'one') - self.assertEqual(f.readline(), 'two') - shell.push(['one\n', 'two\n', 'three\n']) - self.assertEqual(f.readline(2), 'on') - self.assertEqual(f.readline(1), 'e') - self.assertEqual(f.readline(1), '\n') - self.assertEqual(f.readline(10), 'two\n') - - shell.push(['one\n', 'two\n']) - self.assertEqual(f.readline(0), '') - self.assertRaises(TypeError, f.readlines, 1.5) - self.assertRaises(TypeError, f.readlines, '1') - self.assertRaises(TypeError, f.readlines, 1, 1) - - def test_readlines(self): - shell = MockShell() - f = PseudoInputFile(shell, 'stdin', 'utf-8') - shell.push(['one\n', 'two\n', '']) - self.assertEqual(f.readlines(), ['one\n', 'two\n']) - shell.push(['one\n', 'two\n', '']) - self.assertEqual(f.readlines(-1), ['one\n', 'two\n']) - shell.push(['one\n', 'two\n', '']) - self.assertEqual(f.readlines(None), ['one\n', 'two\n']) - shell.push(['one\n', 'two\n', '']) - self.assertEqual(f.readlines(0), ['one\n', 'two\n']) - shell.push(['one\n', 'two\n', '']) - self.assertEqual(f.readlines(3), ['one\n']) - shell.push(['one\n', 'two\n', '']) - self.assertEqual(f.readlines(4), ['one\n', 'two\n']) - - shell.push(['one\n', 'two\n', '']) - self.assertRaises(TypeError, f.readlines, 1.5) - self.assertRaises(TypeError, f.readlines, '1') - self.assertRaises(TypeError, f.readlines, 1, 1) - - def test_close(self): - shell = MockShell() - f = PseudoInputFile(shell, 'stdin', 'utf-8') - shell.push(['one\n', 'two\n', '']) - self.assertFalse(f.closed) - self.assertEqual(f.readline(), 'one\n') - f.close() - self.assertFalse(f.closed) - self.assertEqual(f.readline(), 'two\n') - self.assertRaises(TypeError, f.close, 1) +from idlelib import iomenu +import unittest +from test.support import requires +from tkinter import Tk + +from idlelib.editor import EditorWindow + + +class IOBindigTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + cls.root = Tk() + cls.root.withdraw() + cls.editwin = EditorWindow(root=cls.root) + + @classmethod + def tearDownClass(cls): + cls.editwin._close() + del cls.editwin + cls.root.update_idletasks() + for id in cls.root.tk.call('after', 'info'): + cls.root.after_cancel(id) # Need for EditorWindow. + cls.root.destroy() + del cls.root + + def test_init(self): + io = iomenu.IOBinding(self.editwin) + self.assertIs(io.editwin, self.editwin) + io.close if __name__ == '__main__': diff --git a/Lib/idlelib/idle_test/test_macosx.py b/Lib/idlelib/idle_test/test_macosx.py index 3d85f3c..b6bd922 100644 --- a/Lib/idlelib/idle_test/test_macosx.py +++ b/Lib/idlelib/idle_test/test_macosx.py @@ -1,11 +1,9 @@ -'''Test idlelib.macosx.py. +"Test macosx, coverage 45% on Windows." -Coverage: 71% on Windows. -''' from idlelib import macosx +import unittest from test.support import requires import tkinter as tk -import unittest import unittest.mock as mock from idlelib.filelist import FileList diff --git a/Lib/idlelib/idle_test/test_mainmenu.py b/Lib/idlelib/idle_test/test_mainmenu.py new file mode 100644 index 0000000..0471128 --- /dev/null +++ b/Lib/idlelib/idle_test/test_mainmenu.py @@ -0,0 +1,21 @@ +"Test mainmenu, coverage 100%." +# Reported as 88%; mocking turtledemo absence would have no point. + +from idlelib import mainmenu +import unittest + + +class MainMenuTest(unittest.TestCase): + + def test_menudefs(self): + actual = [item[0] for item in mainmenu.menudefs] + expect = ['file', 'edit', 'format', 'run', 'shell', + 'debug', 'options', 'windows', 'help'] + self.assertEqual(actual, expect) + + def test_default_keydefs(self): + self.assertGreaterEqual(len(mainmenu.default_keydefs), 50) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_multicall.py b/Lib/idlelib/idle_test/test_multicall.py new file mode 100644 index 0000000..68156a7 --- /dev/null +++ b/Lib/idlelib/idle_test/test_multicall.py @@ -0,0 +1,40 @@ +"Test multicall, coverage 33%." + +from idlelib import multicall +import unittest +from test.support import requires +from tkinter import Tk, Text + + +class MultiCallTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + cls.root = Tk() + cls.root.withdraw() + cls.mc = multicall.MultiCallCreator(Text) + + @classmethod + def tearDownClass(cls): + del cls.mc + cls.root.update_idletasks() +## for id in cls.root.tk.call('after', 'info'): +## cls.root.after_cancel(id) # Need for EditorWindow. + cls.root.destroy() + del cls.root + + def test_creator(self): + mc = self.mc + self.assertIs(multicall._multicall_dict[Text], mc) + self.assertTrue(issubclass(mc, Text)) + mc2 = multicall.MultiCallCreator(Text) + self.assertIs(mc, mc2) + + def test_init(self): + mctext = self.mc(self.root) + self.assertIsInstance(mctext._MultiCall__binders, list) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_outwin.py b/Lib/idlelib/idle_test/test_outwin.py index 231c7bf..cd099ec 100644 --- a/Lib/idlelib/idle_test/test_outwin.py +++ b/Lib/idlelib/idle_test/test_outwin.py @@ -1,12 +1,11 @@ -""" Test idlelib.outwin. -""" +"Test outwin, coverage 76%." +from idlelib import outwin import unittest +from test.support import requires from tkinter import Tk, Text from idlelib.idle_test.mock_tk import Mbox_func from idlelib.idle_test.mock_idle import Func -from idlelib import outwin -from test.support import requires from unittest import mock diff --git a/Lib/idlelib/idle_test/test_paragraph.py b/Lib/idlelib/idle_test/test_paragraph.py index ba350c9..0cb966f 100644 --- a/Lib/idlelib/idle_test/test_paragraph.py +++ b/Lib/idlelib/idle_test/test_paragraph.py @@ -1,9 +1,10 @@ -# Test the functions and main class method of paragraph.py +"Test paragraph, coverage 76%." + +from idlelib import paragraph as pg import unittest -from idlelib import paragraph as fp -from idlelib.editor import EditorWindow -from tkinter import Tk, Text from test.support import requires +from tkinter import Tk, Text +from idlelib.editor import EditorWindow class Is_Get_Test(unittest.TestCase): @@ -15,26 +16,26 @@ class Is_Get_Test(unittest.TestCase): leadingws_nocomment = ' This is not a comment' def test_is_all_white(self): - self.assertTrue(fp.is_all_white('')) - self.assertTrue(fp.is_all_white('\t\n\r\f\v')) - self.assertFalse(fp.is_all_white(self.test_comment)) + self.assertTrue(pg.is_all_white('')) + self.assertTrue(pg.is_all_white('\t\n\r\f\v')) + self.assertFalse(pg.is_all_white(self.test_comment)) def test_get_indent(self): Equal = self.assertEqual - Equal(fp.get_indent(self.test_comment), '') - Equal(fp.get_indent(self.trailingws_comment), '') - Equal(fp.get_indent(self.leadingws_comment), ' ') - Equal(fp.get_indent(self.leadingws_nocomment), ' ') + Equal(pg.get_indent(self.test_comment), '') + Equal(pg.get_indent(self.trailingws_comment), '') + Equal(pg.get_indent(self.leadingws_comment), ' ') + Equal(pg.get_indent(self.leadingws_nocomment), ' ') def test_get_comment_header(self): Equal = self.assertEqual # Test comment strings - Equal(fp.get_comment_header(self.test_comment), '#') - Equal(fp.get_comment_header(self.trailingws_comment), '#') - Equal(fp.get_comment_header(self.leadingws_comment), ' #') + Equal(pg.get_comment_header(self.test_comment), '#') + Equal(pg.get_comment_header(self.trailingws_comment), '#') + Equal(pg.get_comment_header(self.leadingws_comment), ' #') # Test non-comment strings - Equal(fp.get_comment_header(self.leadingws_nocomment), ' ') - Equal(fp.get_comment_header(self.test_nocomment), '') + Equal(pg.get_comment_header(self.leadingws_nocomment), ' ') + Equal(pg.get_comment_header(self.test_nocomment), '') class FindTest(unittest.TestCase): @@ -62,7 +63,7 @@ class FindTest(unittest.TestCase): linelength = int(text.index("%d.end" % line).split('.')[1]) for col in (0, linelength//2, linelength): tempindex = "%d.%d" % (line, col) - self.assertEqual(fp.find_paragraph(text, tempindex), expected) + self.assertEqual(pg.find_paragraph(text, tempindex), expected) text.delete('1.0', 'end') def test_find_comment(self): @@ -161,7 +162,7 @@ class ReformatFunctionTest(unittest.TestCase): def test_reformat_paragraph(self): Equal = self.assertEqual - reform = fp.reformat_paragraph + reform = pg.reformat_paragraph hw = "O hello world" Equal(reform(' ', 1), ' ') Equal(reform("Hello world", 20), "Hello world") @@ -192,7 +193,7 @@ class ReformatCommentTest(unittest.TestCase): test_string = ( " \"\"\"this is a test of a reformat for a triple quoted string" " will it reformat to less than 70 characters for me?\"\"\"") - result = fp.reformat_comment(test_string, 70, " ") + result = pg.reformat_comment(test_string, 70, " ") expected = ( " \"\"\"this is a test of a reformat for a triple quoted string will it\n" " reformat to less than 70 characters for me?\"\"\"") @@ -201,7 +202,7 @@ class ReformatCommentTest(unittest.TestCase): test_comment = ( "# this is a test of a reformat for a triple quoted string will " "it reformat to less than 70 characters for me?") - result = fp.reformat_comment(test_comment, 70, "#") + result = pg.reformat_comment(test_comment, 70, "#") expected = ( "# this is a test of a reformat for a triple quoted string will it\n" "# reformat to less than 70 characters for me?") @@ -210,7 +211,7 @@ class ReformatCommentTest(unittest.TestCase): class FormatClassTest(unittest.TestCase): def test_init_close(self): - instance = fp.FormatParagraph('editor') + instance = pg.FormatParagraph('editor') self.assertEqual(instance.editwin, 'editor') instance.close() self.assertEqual(instance.editwin, None) @@ -269,14 +270,16 @@ class FormatEventTest(unittest.TestCase): def setUpClass(cls): requires('gui') cls.root = Tk() + cls.root.withdraw() editor = Editor(root=cls.root) cls.text = editor.text.text # Test code does not need the wrapper. - cls.formatter = fp.FormatParagraph(editor).format_paragraph_event + cls.formatter = pg.FormatParagraph(editor).format_paragraph_event # Sets the insert mark just after the re-wrapped and inserted text. @classmethod def tearDownClass(cls): del cls.text, cls.formatter + cls.root.update_idletasks() cls.root.destroy() del cls.root diff --git a/Lib/idlelib/idle_test/test_parenmatch.py b/Lib/idlelib/idle_test/test_parenmatch.py index 3caa275..f58819a 100644 --- a/Lib/idlelib/idle_test/test_parenmatch.py +++ b/Lib/idlelib/idle_test/test_parenmatch.py @@ -1,8 +1,8 @@ -'''Test idlelib.parenmatch. +"""Test parenmatch, coverage 91%. This must currently be a gui test because ParenMatch methods use several text methods not defined on idlelib.idle_test.mock_tk.Text. -''' +""" from idlelib.parenmatch import ParenMatch from test.support import requires requires('gui') diff --git a/Lib/idlelib/idle_test/test_pathbrowser.py b/Lib/idlelib/idle_test/test_pathbrowser.py index 74b716a..13d8b9e 100644 --- a/Lib/idlelib/idle_test/test_pathbrowser.py +++ b/Lib/idlelib/idle_test/test_pathbrowser.py @@ -1,19 +1,17 @@ -""" Test idlelib.pathbrowser. -""" +"Test pathbrowser, coverage 95%." +from idlelib import pathbrowser +import unittest +from test.support import requires +from tkinter import Tk import os.path import pyclbr # for _modules import sys # for sys.path -from tkinter import Tk -from test.support import requires -import unittest from idlelib.idle_test.mock_idle import Func - import idlelib # for __file__ from idlelib import browser -from idlelib import pathbrowser from idlelib.tree import TreeNode diff --git a/Lib/idlelib/idle_test/test_percolator.py b/Lib/idlelib/idle_test/test_percolator.py index 573b9a1..17668cc 100644 --- a/Lib/idlelib/idle_test/test_percolator.py +++ b/Lib/idlelib/idle_test/test_percolator.py @@ -1,10 +1,10 @@ -'''Test percolator.py.''' -from test.support import requires -requires('gui') +"Test percolator, coverage 100%." +from idlelib.percolator import Percolator, Delegator import unittest +from test.support import requires +requires('gui') from tkinter import Text, Tk, END -from idlelib.percolator import Percolator, Delegator class MyFilter(Delegator): diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index 574b19d..0534301 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -1,11 +1,8 @@ -"""Unittest for idlelib.pyparse.py. +"Test pyparse, coverage 96%." -Coverage: 97% -""" - -from collections import namedtuple -import unittest from idlelib import pyparse +import unittest +from collections import namedtuple class ParseMapTest(unittest.TestCase): diff --git a/Lib/idlelib/idle_test/test_pyshell.py b/Lib/idlelib/idle_test/test_pyshell.py new file mode 100644 index 0000000..581444c --- /dev/null +++ b/Lib/idlelib/idle_test/test_pyshell.py @@ -0,0 +1,42 @@ +"Test pyshell, coverage 12%." +# Plus coverage of test_warning. Was 20% with test_openshell. + +from idlelib import pyshell +import unittest +from test.support import requires +from tkinter import Tk + + +class PyShellFileListTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + cls.root = Tk() + cls.root.withdraw() + + @classmethod + def tearDownClass(cls): + #cls.root.update_idletasks() +## for id in cls.root.tk.call('after', 'info'): +## cls.root.after_cancel(id) # Need for EditorWindow. + cls.root.destroy() + del cls.root + + def test_init(self): + psfl = pyshell.PyShellFileList(self.root) + self.assertEqual(psfl.EditorWindow, pyshell.PyShellEditorWindow) + self.assertIsNone(psfl.pyshell) + +# The following sometimes causes 'invalid command name "109734456recolorize"'. +# Uncommenting after_cancel above prevents this, but results in +# TclError: bad window path name ".!listedtoplevel.!frame.text" +# which is normally prevented by after_cancel. +## def test_openshell(self): +## pyshell.use_subprocess = False +## ps = pyshell.PyShellFileList(self.root).open_shell() +## self.assertIsInstance(ps, pyshell.PyShell) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py index 953f24f..c1c4a25 100644 --- a/Lib/idlelib/idle_test/test_query.py +++ b/Lib/idlelib/idle_test/test_query.py @@ -1,4 +1,4 @@ -"""Test idlelib.query. +"""Test query, coverage 91%). Non-gui tests for Query, SectionName, ModuleName, and HelpSource use dummy versions that extract the non-gui methods and add other needed @@ -8,17 +8,15 @@ the subclass definition. The appearance of the widgets is checked by the Query and HelpSource htests. These are run by running query.py. - -Coverage: 94% (100% for Query and SectionName). -6 of 8 missing are ModuleName exceptions I don't know how to trigger. """ +from idlelib import query +import unittest from test.support import requires -import sys from tkinter import Tk -import unittest + +import sys from unittest import mock from idlelib.idle_test.mock_tk import Var -from idlelib import query # NON-GUI TESTS diff --git a/Lib/idlelib/idle_test/test_redirector.py b/Lib/idlelib/idle_test/test_redirector.py index b0385fa..a97b300 100644 --- a/Lib/idlelib/idle_test/test_redirector.py +++ b/Lib/idlelib/idle_test/test_redirector.py @@ -1,12 +1,10 @@ -'''Test idlelib.redirector. +"Test redirector, coverage 100%." -100% coverage -''' -from test.support import requires +from idlelib.redirector import WidgetRedirector import unittest -from idlelib.idle_test.mock_idle import Func +from test.support import requires from tkinter import Tk, Text, TclError -from idlelib.redirector import WidgetRedirector +from idlelib.idle_test.mock_idle import Func class InitCloseTest(unittest.TestCase): diff --git a/Lib/idlelib/idle_test/test_replace.py b/Lib/idlelib/idle_test/test_replace.py index df76dec..c3c5d2e 100644 --- a/Lib/idlelib/idle_test/test_replace.py +++ b/Lib/idlelib/idle_test/test_replace.py @@ -1,13 +1,14 @@ -"""Unittest for idlelib.replace.py""" +"Test replace, coverage 78%." + +from idlelib.replace import ReplaceDialog +import unittest from test.support import requires requires('gui') +from tkinter import Tk, Text -import unittest from unittest.mock import Mock -from tkinter import Tk, Text from idlelib.idle_test.mock_tk import Mbox import idlelib.searchengine as se -from idlelib.replace import ReplaceDialog orig_mbox = se.tkMessageBox showerror = Mbox.showerror diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py index d7e627d..46f0235 100644 --- a/Lib/idlelib/idle_test/test_run.py +++ b/Lib/idlelib/idle_test/test_run.py @@ -1,11 +1,14 @@ +"Test run, coverage 42%." + +from idlelib import run import unittest from unittest import mock - from test.support import captured_stderr -import idlelib.run as idlerun +import io class RunTest(unittest.TestCase): + def test_print_exception_unhashable(self): class UnhashableException(Exception): def __eq__(self, other): @@ -20,10 +23,10 @@ class RunTest(unittest.TestCase): raise ex1 except UnhashableException: with captured_stderr() as output: - with mock.patch.object(idlerun, + with mock.patch.object(run, 'cleanup_traceback') as ct: ct.side_effect = lambda t, e: t - idlerun.print_exception() + run.print_exception() tb = output.getvalue().strip().splitlines() self.assertEqual(11, len(tb)) @@ -31,5 +34,231 @@ class RunTest(unittest.TestCase): self.assertIn('UnhashableException: ex1', tb[10]) +# PseudoFile tests. + +class S(str): + def __str__(self): + return '%s:str' % type(self).__name__ + def __unicode__(self): + return '%s:unicode' % type(self).__name__ + def __len__(self): + return 3 + def __iter__(self): + return iter('abc') + def __getitem__(self, *args): + return '%s:item' % type(self).__name__ + def __getslice__(self, *args): + return '%s:slice' % type(self).__name__ + + +class MockShell: + def __init__(self): + self.reset() + def write(self, *args): + self.written.append(args) + def readline(self): + return self.lines.pop() + def close(self): + pass + def reset(self): + self.written = [] + def push(self, lines): + self.lines = list(lines)[::-1] + + +class PseudeInputFilesTest(unittest.TestCase): + + def test_misc(self): + shell = MockShell() + f = run.PseudoInputFile(shell, 'stdin', 'utf-8') + self.assertIsInstance(f, io.TextIOBase) + self.assertEqual(f.encoding, 'utf-8') + self.assertIsNone(f.errors) + self.assertIsNone(f.newlines) + self.assertEqual(f.name, '') + self.assertFalse(f.closed) + self.assertTrue(f.isatty()) + self.assertTrue(f.readable()) + self.assertFalse(f.writable()) + self.assertFalse(f.seekable()) + + def test_unsupported(self): + shell = MockShell() + f = run.PseudoInputFile(shell, 'stdin', 'utf-8') + self.assertRaises(OSError, f.fileno) + self.assertRaises(OSError, f.tell) + self.assertRaises(OSError, f.seek, 0) + self.assertRaises(OSError, f.write, 'x') + self.assertRaises(OSError, f.writelines, ['x']) + + def test_read(self): + shell = MockShell() + f = run.PseudoInputFile(shell, 'stdin', 'utf-8') + shell.push(['one\n', 'two\n', '']) + self.assertEqual(f.read(), 'one\ntwo\n') + shell.push(['one\n', 'two\n', '']) + self.assertEqual(f.read(-1), 'one\ntwo\n') + shell.push(['one\n', 'two\n', '']) + self.assertEqual(f.read(None), 'one\ntwo\n') + shell.push(['one\n', 'two\n', 'three\n', '']) + self.assertEqual(f.read(2), 'on') + self.assertEqual(f.read(3), 'e\nt') + self.assertEqual(f.read(10), 'wo\nthree\n') + + shell.push(['one\n', 'two\n']) + self.assertEqual(f.read(0), '') + self.assertRaises(TypeError, f.read, 1.5) + self.assertRaises(TypeError, f.read, '1') + self.assertRaises(TypeError, f.read, 1, 1) + + def test_readline(self): + shell = MockShell() + f = run.PseudoInputFile(shell, 'stdin', 'utf-8') + shell.push(['one\n', 'two\n', 'three\n', 'four\n']) + self.assertEqual(f.readline(), 'one\n') + self.assertEqual(f.readline(-1), 'two\n') + self.assertEqual(f.readline(None), 'three\n') + shell.push(['one\ntwo\n']) + self.assertEqual(f.readline(), 'one\n') + self.assertEqual(f.readline(), 'two\n') + shell.push(['one', 'two', 'three']) + self.assertEqual(f.readline(), 'one') + self.assertEqual(f.readline(), 'two') + shell.push(['one\n', 'two\n', 'three\n']) + self.assertEqual(f.readline(2), 'on') + self.assertEqual(f.readline(1), 'e') + self.assertEqual(f.readline(1), '\n') + self.assertEqual(f.readline(10), 'two\n') + + shell.push(['one\n', 'two\n']) + self.assertEqual(f.readline(0), '') + self.assertRaises(TypeError, f.readlines, 1.5) + self.assertRaises(TypeError, f.readlines, '1') + self.assertRaises(TypeError, f.readlines, 1, 1) + + def test_readlines(self): + shell = MockShell() + f = run.PseudoInputFile(shell, 'stdin', 'utf-8') + shell.push(['one\n', 'two\n', '']) + self.assertEqual(f.readlines(), ['one\n', 'two\n']) + shell.push(['one\n', 'two\n', '']) + self.assertEqual(f.readlines(-1), ['one\n', 'two\n']) + shell.push(['one\n', 'two\n', '']) + self.assertEqual(f.readlines(None), ['one\n', 'two\n']) + shell.push(['one\n', 'two\n', '']) + self.assertEqual(f.readlines(0), ['one\n', 'two\n']) + shell.push(['one\n', 'two\n', '']) + self.assertEqual(f.readlines(3), ['one\n']) + shell.push(['one\n', 'two\n', '']) + self.assertEqual(f.readlines(4), ['one\n', 'two\n']) + + shell.push(['one\n', 'two\n', '']) + self.assertRaises(TypeError, f.readlines, 1.5) + self.assertRaises(TypeError, f.readlines, '1') + self.assertRaises(TypeError, f.readlines, 1, 1) + + def test_close(self): + shell = MockShell() + f = run.PseudoInputFile(shell, 'stdin', 'utf-8') + shell.push(['one\n', 'two\n', '']) + self.assertFalse(f.closed) + self.assertEqual(f.readline(), 'one\n') + f.close() + self.assertFalse(f.closed) + self.assertEqual(f.readline(), 'two\n') + self.assertRaises(TypeError, f.close, 1) + + +class PseudeOutputFilesTest(unittest.TestCase): + + def test_misc(self): + shell = MockShell() + f = run.PseudoOutputFile(shell, 'stdout', 'utf-8') + self.assertIsInstance(f, io.TextIOBase) + self.assertEqual(f.encoding, 'utf-8') + self.assertIsNone(f.errors) + self.assertIsNone(f.newlines) + self.assertEqual(f.name, '') + self.assertFalse(f.closed) + self.assertTrue(f.isatty()) + self.assertFalse(f.readable()) + self.assertTrue(f.writable()) + self.assertFalse(f.seekable()) + + def test_unsupported(self): + shell = MockShell() + f = run.PseudoOutputFile(shell, 'stdout', 'utf-8') + self.assertRaises(OSError, f.fileno) + self.assertRaises(OSError, f.tell) + self.assertRaises(OSError, f.seek, 0) + self.assertRaises(OSError, f.read, 0) + self.assertRaises(OSError, f.readline, 0) + + def test_write(self): + shell = MockShell() + f = run.PseudoOutputFile(shell, 'stdout', 'utf-8') + f.write('test') + self.assertEqual(shell.written, [('test', 'stdout')]) + shell.reset() + f.write('t\xe8st') + self.assertEqual(shell.written, [('t\xe8st', 'stdout')]) + shell.reset() + + f.write(S('t\xe8st')) + self.assertEqual(shell.written, [('t\xe8st', 'stdout')]) + self.assertEqual(type(shell.written[0][0]), str) + shell.reset() + + self.assertRaises(TypeError, f.write) + self.assertEqual(shell.written, []) + self.assertRaises(TypeError, f.write, b'test') + self.assertRaises(TypeError, f.write, 123) + self.assertEqual(shell.written, []) + self.assertRaises(TypeError, f.write, 'test', 'spam') + self.assertEqual(shell.written, []) + + def test_writelines(self): + shell = MockShell() + f = run.PseudoOutputFile(shell, 'stdout', 'utf-8') + f.writelines([]) + self.assertEqual(shell.written, []) + shell.reset() + f.writelines(['one\n', 'two']) + self.assertEqual(shell.written, + [('one\n', 'stdout'), ('two', 'stdout')]) + shell.reset() + f.writelines(['on\xe8\n', 'tw\xf2']) + self.assertEqual(shell.written, + [('on\xe8\n', 'stdout'), ('tw\xf2', 'stdout')]) + shell.reset() + + f.writelines([S('t\xe8st')]) + self.assertEqual(shell.written, [('t\xe8st', 'stdout')]) + self.assertEqual(type(shell.written[0][0]), str) + shell.reset() + + self.assertRaises(TypeError, f.writelines) + self.assertEqual(shell.written, []) + self.assertRaises(TypeError, f.writelines, 123) + self.assertEqual(shell.written, []) + self.assertRaises(TypeError, f.writelines, [b'test']) + self.assertRaises(TypeError, f.writelines, [123]) + self.assertEqual(shell.written, []) + self.assertRaises(TypeError, f.writelines, [], []) + self.assertEqual(shell.written, []) + + def test_close(self): + shell = MockShell() + f = run.PseudoOutputFile(shell, 'stdout', 'utf-8') + self.assertFalse(f.closed) + f.write('test') + f.close() + self.assertTrue(f.closed) + self.assertRaises(ValueError, f.write, 'x') + self.assertEqual(shell.written, [('test', 'stdout')]) + f.close() + self.assertRaises(TypeError, f.close, 1) + + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Lib/idlelib/iomenu.py b/Lib/idlelib/iomenu.py index f9b6907..63d107d 100644 --- a/Lib/idlelib/iomenu.py +++ b/Lib/idlelib/iomenu.py @@ -567,8 +567,8 @@ def _io_binding(parent): # htest # IOBinding(editwin) if __name__ == "__main__": - import unittest - unittest.main('idlelib.idle_test.test_iomenu', verbosity=2, exit=False) + from unittest import main + main('idlelib.idle_test.test_iomenu', verbosity=2, exit=False) from idlelib.idle_test.htest import run run(_io_binding) diff --git a/Lib/idlelib/mainmenu.py b/Lib/idlelib/mainmenu.py index 143570d..04acaed 100644 --- a/Lib/idlelib/mainmenu.py +++ b/Lib/idlelib/mainmenu.py @@ -36,7 +36,8 @@ menudefs = [ None, ('_Close', '<>'), ('E_xit', '<>'), - ]), + ]), + ('edit', [ ('_Undo', '<>'), ('_Redo', '<>'), @@ -56,9 +57,9 @@ menudefs = [ ('E_xpand Word', '<>'), ('Show C_all Tip', '<>'), ('Show Surrounding P_arens', '<>'), + ]), - ]), -('format', [ + ('format', [ ('_Indent Region', '<>'), ('_Dedent Region', '<>'), ('Comment _Out Region', '<>'), @@ -70,30 +71,36 @@ menudefs = [ ('F_ormat Paragraph', '<>'), ('S_trip Trailing Whitespace', '<>'), ]), + ('run', [ ('Python Shell', '<>'), ('C_heck Module', '<>'), ('R_un Module', '<>'), ]), + ('shell', [ ('_View Last Restart', '<>'), ('_Restart Shell', '<>'), None, ('_Interrupt Execution', '<>'), ]), + ('debug', [ ('_Go to File/Line', '<>'), ('!_Debugger', '<>'), ('_Stack Viewer', '<>'), ('!_Auto-open Stack Viewer', '<>'), ]), + ('options', [ ('Configure _IDLE', '<>'), ('_Code Context', '<>'), ]), + ('windows', [ ('Zoom Height', '<>'), ]), + ('help', [ ('_About IDLE', '<>'), None, @@ -106,3 +113,7 @@ if find_spec('turtledemo'): menudefs[-1][1].append(('Turtle Demo', '<>')) default_keydefs = idleConf.GetCurrentKeySet() + +if __name__ == '__main__': + from unittest import main + main('idlelib.idle_test.test_mainmenu', verbosity=2) diff --git a/Lib/idlelib/multicall.py b/Lib/idlelib/multicall.py index b74fed4..dc02001 100644 --- a/Lib/idlelib/multicall.py +++ b/Lib/idlelib/multicall.py @@ -441,5 +441,8 @@ def _multi_call(parent): # htest # bindseq("") if __name__ == "__main__": + from unittest import main + main('idlelib.idle_test.test_mainmenu', verbosity=2, exit=False) + from idlelib.idle_test.htest import run run(_multi_call) diff --git a/Lib/idlelib/paragraph.py b/Lib/idlelib/paragraph.py index 1270115..8142257 100644 --- a/Lib/idlelib/paragraph.py +++ b/Lib/idlelib/paragraph.py @@ -190,6 +190,5 @@ def get_comment_header(line): if __name__ == "__main__": - import unittest - unittest.main('idlelib.idle_test.test_paragraph', - verbosity=2, exit=False) + from unittest import main + main('idlelib.idle_test.test_paragraph', verbosity=2, exit=False) diff --git a/Lib/idlelib/parenmatch.py b/Lib/idlelib/parenmatch.py index 983ca20..3fd7aad 100644 --- a/Lib/idlelib/parenmatch.py +++ b/Lib/idlelib/parenmatch.py @@ -179,5 +179,5 @@ ParenMatch.reload() if __name__ == '__main__': - import unittest - unittest.main('idlelib.idle_test.test_parenmatch', verbosity=2) + from unittest import main + main('idlelib.idle_test.test_parenmatch', verbosity=2) diff --git a/Lib/idlelib/percolator.py b/Lib/idlelib/percolator.py index d18daf0..db70304 100644 --- a/Lib/idlelib/percolator.py +++ b/Lib/idlelib/percolator.py @@ -96,9 +96,8 @@ def _percolator(parent): # htest # cb2.pack() if __name__ == "__main__": - import unittest - unittest.main('idlelib.idle_test.test_percolator', verbosity=2, - exit=False) + from unittest import main + main('idlelib.idle_test.test_percolator', verbosity=2, exit=False) from idlelib.idle_test.htest import run run(_percolator) diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 6196c2b..1eeb915 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -594,6 +594,6 @@ class Parser: return self.stmt_bracketing -if __name__ == '__main__': #pragma: nocover - import unittest - unittest.main('idlelib.idle_test.test_pyparse', verbosity=2) +if __name__ == '__main__': + from unittest import main + main('idlelib.idle_test.test_pyparse', verbosity=2) diff --git a/Lib/idlelib/query.py b/Lib/idlelib/query.py index 5935063..15add6d 100644 --- a/Lib/idlelib/query.py +++ b/Lib/idlelib/query.py @@ -301,8 +301,8 @@ class HelpSource(Query): if __name__ == '__main__': - import unittest - unittest.main('idlelib.idle_test.test_query', verbosity=2, exit=False) + from unittest import main + main('idlelib.idle_test.test_query', verbosity=2, exit=False) from idlelib.idle_test.htest import run run(Query, HelpSource) diff --git a/Lib/idlelib/redirector.py b/Lib/idlelib/redirector.py index ec681de..9ab34c5 100644 --- a/Lib/idlelib/redirector.py +++ b/Lib/idlelib/redirector.py @@ -167,9 +167,8 @@ def _widget_redirector(parent): # htest # original_insert = redir.register("insert", my_insert) if __name__ == "__main__": - import unittest - unittest.main('idlelib.idle_test.test_redirector', - verbosity=2, exit=False) + from unittest import main + main('idlelib.idle_test.test_redirector', verbosity=2, exit=False) from idlelib.idle_test.htest import run run(_widget_redirector) diff --git a/Lib/idlelib/replace.py b/Lib/idlelib/replace.py index abd9e59..83cf987 100644 --- a/Lib/idlelib/replace.py +++ b/Lib/idlelib/replace.py @@ -235,9 +235,8 @@ def _replace_dialog(parent): # htest # button.pack() if __name__ == '__main__': - import unittest - unittest.main('idlelib.idle_test.test_replace', - verbosity=2, exit=False) + from unittest import main + main('idlelib.idle_test.test_replace', verbosity=2, exit=False) from idlelib.idle_test.htest import run run(_replace_dialog) -- cgit v0.12