Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
dfa9643d
Commit
dfa9643d
authored
Jun 14, 2018
by
Jaysinh Shukla
Committed by
Victor Stinner
Jun 14, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-19382: Adding test cases for module tabnanny (GH-851)
Testing strategy: whitebox.
parent
ab4a1988
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
344 additions
and
1 deletion
+344
-1
Lib/test/test_sundry.py
Lib/test/test_sundry.py
+1
-1
Lib/test/test_tabnanny.py
Lib/test/test_tabnanny.py
+343
-0
No files found.
Lib/test/test_sundry.py
View file @
dfa9643d
...
...
@@ -6,7 +6,7 @@ import unittest
class
TestUntestedModules
(
unittest
.
TestCase
):
def
test_untested_modules_can_be_imported
(
self
):
untested
=
(
'encodings'
,
'formatter'
,
'tabnanny'
)
untested
=
(
'encodings'
,
'formatter'
)
with
support
.
check_warnings
(
quiet
=
True
):
for
name
in
untested
:
try
:
...
...
Lib/test/test_tabnanny.py
0 → 100644
View file @
dfa9643d
"""Testing `tabnanny` module.
Glossary:
* errored : Whitespace related problems present in file.
"""
from
unittest
import
TestCase
,
mock
from
unittest
import
mock
import
tabnanny
import
tokenize
import
tempfile
import
textwrap
from
test.support
import
(
captured_stderr
,
captured_stdout
,
script_helper
,
findfile
,
unlink
)
SOURCE_CODES
=
{
"incomplete_expression"
:
(
'fruits = [
\
n
'
' "Apple",
\
n
'
' "Orange",
\
n
'
' "Banana",
\
n
'
'
\
n
'
'print(fruits)
\
n
'
),
"wrong_indented"
:
(
'if True:
\
n
'
' print("hello")
\
n
'
' print("world")
\
n
'
'else:
\
n
'
' print("else called")
\
n
'
),
"nannynag_errored"
:
(
'if True:
\
n
'
'
\
t
print("hello")
\
n
'
'
\
t
print("world")
\
n
'
'else:
\
n
'
' print("else called")
\
n
'
),
"error_free"
:
(
'if True:
\
n
'
' print("hello")
\
n
'
' print("world")
\
n
'
'else:
\
n
'
' print("else called")
\
n
'
),
"tab_space_errored_1"
:
(
'def my_func():
\
n
'
'
\
t
print("hello world")
\
n
'
'
\
t
if True:
\
n
'
'
\
t
\
t
print("If called")'
),
"tab_space_errored_2"
:
(
'def my_func():
\
n
'
'
\
t
\
t
print("Hello world")
\
n
'
'
\
t
\
t
if True:
\
n
'
'
\
t
print("If called")'
)
}
class
TemporaryPyFile
:
"""Create a temporary python source code file."""
def
__init__
(
self
,
source_code
=
''
,
directory
=
None
):
self
.
source_code
=
source_code
self
.
dir
=
directory
def
__enter__
(
self
):
with
tempfile
.
NamedTemporaryFile
(
mode
=
'w'
,
dir
=
self
.
dir
,
suffix
=
".py"
,
delete
=
False
)
as
f
:
f
.
write
(
self
.
source_code
)
self
.
file_path
=
f
.
name
return
self
.
file_path
def
__exit__
(
self
,
exc_type
,
exc_value
,
exc_traceback
):
unlink
(
self
.
file_path
)
class
TestFormatWitnesses
(
TestCase
):
"""Testing `tabnanny.format_witnesses()`."""
def
test_format_witnesses
(
self
):
"""Asserting formatter result by giving various input samples."""
tests
=
[
(
'Test'
,
'at tab sizes T, e, s, t'
),
(
''
,
'at tab size '
),
(
't'
,
'at tab size t'
),
(
' t '
,
'at tab sizes , , t, , '
),
]
for
words
,
expected
in
tests
:
with
self
.
subTest
(
words
=
words
,
expected
=
expected
):
self
.
assertEqual
(
tabnanny
.
format_witnesses
(
words
),
expected
)
class
TestErrPrint
(
TestCase
):
"""Testing `tabnanny.errprint()`."""
def
test_errprint
(
self
):
"""Asserting result of `tabnanny.errprint()` by giving sample inputs."""
tests
=
[
([
'first'
,
'second'
],
'first second
\
n
'
),
([
'first'
],
'first
\
n
'
),
([
1
,
2
,
3
],
'1 2 3
\
n
'
),
([],
'
\
n
'
)
]
for
args
,
expected
in
tests
:
with
self
.
subTest
(
arguments
=
args
,
expected
=
expected
):
with
captured_stderr
()
as
stderr
:
tabnanny
.
errprint
(
*
args
)
self
.
assertEqual
(
stderr
.
getvalue
()
,
expected
)
class
TestNannyNag
(
TestCase
):
def
test_all_methods
(
self
):
"""Asserting behaviour of `tabnanny.NannyNag` exception."""
tests
=
[
(
tabnanny
.
NannyNag
(
0
,
"foo"
,
"bar"
),
{
'lineno'
:
0
,
'msg'
:
'foo'
,
'line'
:
'bar'
}
),
(
tabnanny
.
NannyNag
(
5
,
"testmsg"
,
"testline"
),
{
'lineno'
:
5
,
'msg'
:
'testmsg'
,
'line'
:
'testline'
}
)
]
for
nanny
,
expected
in
tests
:
line_number
=
nanny
.
get_lineno
()
msg
=
nanny
.
get_msg
()
line
=
nanny
.
get_line
()
with
self
.
subTest
(
line_number
=
line_number
,
expected
=
expected
[
'lineno'
]
):
self
.
assertEqual
(
expected
[
'lineno'
],
line_number
)
with
self
.
subTest
(
msg
=
msg
,
expected
=
expected
[
'msg'
]):
self
.
assertEqual
(
expected
[
'msg'
],
msg
)
with
self
.
subTest
(
line
=
line
,
expected
=
expected
[
'line'
]):
self
.
assertEqual
(
expected
[
'line'
],
line
)
class
TestCheck
(
TestCase
):
"""Testing tabnanny.check()."""
def
setUp
(
self
):
self
.
addCleanup
(
setattr
,
tabnanny
,
'verbose'
,
tabnanny
.
verbose
)
tabnanny
.
verbose
=
0
# Forcefully deactivating verbose mode.
def
verify_tabnanny_check
(
self
,
dir_or_file
,
out
=
""
,
err
=
""
):
"""Common verification for tabnanny.check().
Use this method to assert expected values of `stdout` and `stderr` after
running tabnanny.check() on given `dir` or `file` path. Because
tabnanny.check() captures exceptions and writes to `stdout` and
`stderr`, asserting standard outputs is the only way.
"""
with
captured_stdout
()
as
stdout
,
captured_stderr
()
as
stderr
:
tabnanny
.
check
(
dir_or_file
)
self
.
assertEqual
(
stdout
.
getvalue
(),
out
)
self
.
assertEqual
(
stderr
.
getvalue
(),
err
)
def
test_correct_file
(
self
):
"""A python source code file without any errors."""
with
TemporaryPyFile
(
SOURCE_CODES
[
"error_free"
])
as
file_path
:
self
.
verify_tabnanny_check
(
file_path
)
def
test_correct_directory_verbose
(
self
):
"""Directory containing few error free python source code files.
Because order of files returned by `os.lsdir()` is not fixed, verify the
existence of each output lines at `stdout` using `in` operator.
`verbose` mode of `tabnanny.verbose` asserts `stdout`.
"""
with
tempfile
.
TemporaryDirectory
()
as
tmp_dir
:
lines
=
[
f"
{
tmp_dir
!
r
}
: listing directory
\
n
"
,]
file1
=
TemporaryPyFile
(
SOURCE_CODES
[
"error_free"
],
directory
=
tmp_dir
)
file2
=
TemporaryPyFile
(
SOURCE_CODES
[
"error_free"
],
directory
=
tmp_dir
)
with
file1
as
file1_path
,
file2
as
file2_path
:
for
file_path
in
(
file1_path
,
file2_path
):
lines
.
append
(
f"
{
file_path
!
r
}
: Clean bill of health.
\
n
"
)
tabnanny
.
verbose
=
1
with
captured_stdout
()
as
stdout
,
captured_stderr
()
as
stderr
:
tabnanny
.
check
(
tmp_dir
)
stdout
=
stdout
.
getvalue
()
for
line
in
lines
:
with
self
.
subTest
(
line
=
line
):
self
.
assertIn
(
line
,
stdout
)
self
.
assertEqual
(
stderr
.
getvalue
(),
""
)
def
test_correct_directory
(
self
):
"""Directory which contains few error free python source code files."""
with
tempfile
.
TemporaryDirectory
()
as
tmp_dir
:
with
TemporaryPyFile
(
SOURCE_CODES
[
"error_free"
],
directory
=
tmp_dir
):
self
.
verify_tabnanny_check
(
tmp_dir
)
def
test_when_wrong_indented
(
self
):
"""A python source code file eligible for raising `IndentationError`."""
with
TemporaryPyFile
(
SOURCE_CODES
[
"wrong_indented"
])
as
file_path
:
err
=
(
'unindent does not match any outer indentation level'
' (<tokenize>, line 3)
\
n
'
)
err
=
f"
{
file_path
!
r
}
: Indentation Error:
{
err
}
"
self
.
verify_tabnanny_check
(
file_path
,
err
=
err
)
def
test_when_tokenize_tokenerror
(
self
):
"""A python source code file eligible for raising 'tokenize.TokenError'."""
with
TemporaryPyFile
(
SOURCE_CODES
[
"incomplete_expression"
])
as
file_path
:
err
=
"('EOF in multi-line statement', (7, 0))
\
n
"
err
=
f"
{
file_path
!
r
}
: Token Error:
{
err
}
"
self
.
verify_tabnanny_check
(
file_path
,
err
=
err
)
def
test_when_nannynag_error_verbose
(
self
):
"""A python source code file eligible for raising `tabnanny.NannyNag`.
Tests will assert `stdout` after activating `tabnanny.verbose` mode.
"""
with
TemporaryPyFile
(
SOURCE_CODES
[
"nannynag_errored"
])
as
file_path
:
out
=
f"
{
file_path
!
r
}
: *** Line 3: trouble in tab city! ***
\
n
"
out
+=
"offending line: '
\
\
tprint(
\
"
world
\
"
)
\
\
n'
\
n
"
out
+=
"indent not equal e.g. at tab size 1
\
n
"
tabnanny
.
verbose
=
1
self
.
verify_tabnanny_check
(
file_path
,
out
=
out
)
def
test_when_nannynag_error
(
self
):
"""A python source code file eligible for raising `tabnanny.NannyNag`."""
with
TemporaryPyFile
(
SOURCE_CODES
[
"nannynag_errored"
])
as
file_path
:
out
=
f"
{
file_path
}
3 '
\
\
tprint(
\
"
world
\
"
)
\
\
n'
\
n
"
self
.
verify_tabnanny_check
(
file_path
,
out
=
out
)
def
test_when_no_file
(
self
):
"""A python file which does not exist actually in system."""
path
=
'no_file.py'
err
=
f"
{
path
!
r
}
: I/O Error: [Errno 2] No such file or directory:
{
path
!
r
}\
n
"
self
.
verify_tabnanny_check
(
path
,
err
=
err
)
def
test_errored_directory
(
self
):
"""Directory containing wrongly indented python source code files."""
with
tempfile
.
TemporaryDirectory
()
as
tmp_dir
:
error_file
=
TemporaryPyFile
(
SOURCE_CODES
[
"wrong_indented"
],
directory
=
tmp_dir
)
code_file
=
TemporaryPyFile
(
SOURCE_CODES
[
"error_free"
],
directory
=
tmp_dir
)
with
error_file
as
e_file
,
code_file
as
c_file
:
err
=
(
'unindent does not match any outer indentation level'
' (<tokenize>, line 3)
\
n
'
)
err
=
f"
{
e_file
!
r
}
: Indentation Error:
{
err
}
"
self
.
verify_tabnanny_check
(
tmp_dir
,
err
=
err
)
class
TestProcessTokens
(
TestCase
):
"""Testing `tabnanny.process_tokens()`."""
@
mock
.
patch
(
'tabnanny.NannyNag'
)
def
test_with_correct_code
(
self
,
MockNannyNag
):
"""A python source code without any whitespace related problems."""
with
TemporaryPyFile
(
SOURCE_CODES
[
"error_free"
])
as
file_path
:
with
open
(
file_path
)
as
f
:
tabnanny
.
process_tokens
(
tokenize
.
generate_tokens
(
f
.
readline
))
self
.
assertFalse
(
MockNannyNag
.
called
)
def
test_with_errored_codes_samples
(
self
):
"""A python source code with whitespace related sampled problems."""
# "tab_space_errored_1": executes block under type == tokenize.INDENT
# at `tabnanny.process_tokens()`.
# "tab space_errored_2": executes block under
# `check_equal and type not in JUNK` condition at
# `tabnanny.process_tokens()`.
for
key
in
[
"tab_space_errored_1"
,
"tab_space_errored_2"
]:
with
self
.
subTest
(
key
=
key
):
with
TemporaryPyFile
(
SOURCE_CODES
[
key
])
as
file_path
:
with
open
(
file_path
)
as
f
:
tokens
=
tokenize
.
generate_tokens
(
f
.
readline
)
with
self
.
assertRaises
(
tabnanny
.
NannyNag
):
tabnanny
.
process_tokens
(
tokens
)
class
TestCommandLine
(
TestCase
):
"""Tests command line interface of `tabnanny`."""
def
validate_cmd
(
self
,
*
args
,
stdout
=
""
,
stderr
=
""
,
partial
=
False
):
"""Common function to assert the behaviour of command line interface."""
_
,
out
,
err
=
script_helper
.
assert_python_ok
(
'-m'
,
'tabnanny'
,
*
args
)
# Note: The `splitlines()` will solve the problem of CRLF(\r) added
# by OS Windows.
out
=
out
.
decode
(
'ascii'
)
err
=
err
.
decode
(
'ascii'
)
if
partial
:
for
std
,
output
in
((
stdout
,
out
),
(
stderr
,
err
)):
_output
=
output
.
splitlines
()
for
_std
in
std
.
splitlines
():
with
self
.
subTest
(
std
=
_std
,
output
=
_output
):
self
.
assertIn
(
_std
,
_output
)
else
:
self
.
assertListEqual
(
out
.
splitlines
(),
stdout
.
splitlines
())
self
.
assertListEqual
(
err
.
splitlines
(),
stderr
.
splitlines
())
def
test_with_errored_file
(
self
):
"""Should displays error when errored python file is given."""
with
TemporaryPyFile
(
SOURCE_CODES
[
"wrong_indented"
])
as
file_path
:
stderr
=
f"
{
file_path
!
r
}
: Indentation Error: "
stderr
+=
(
'unindent does not match any outer indentation level'
' (<tokenize>, line 3)'
)
self
.
validate_cmd
(
file_path
,
stderr
=
stderr
)
def
test_with_error_free_file
(
self
):
"""Should not display anything if python file is correctly indented."""
with
TemporaryPyFile
(
SOURCE_CODES
[
"error_free"
])
as
file_path
:
self
.
validate_cmd
(
file_path
)
def
test_command_usage
(
self
):
"""Should display usage on no arguments."""
path
=
findfile
(
'tabnanny.py'
)
stderr
=
f"Usage:
{
path
}
[-v] file_or_directory ..."
self
.
validate_cmd
(
stderr
=
stderr
)
def
test_quiet_flag
(
self
):
"""Should display less when quite mode is on."""
with
TemporaryPyFile
(
SOURCE_CODES
[
"nannynag_errored"
])
as
file_path
:
stdout
=
f"
{
file_path
}\
n
"
self
.
validate_cmd
(
"-q"
,
file_path
,
stdout
=
stdout
)
def
test_verbose_mode
(
self
):
"""Should display more error information if verbose mode is on."""
with
TemporaryPyFile
(
SOURCE_CODES
[
"nannynag_errored"
])
as
path
:
stdout
=
textwrap
.
dedent
(
"offending line: '
\
\
tprint(
\
"
world
\
"
)
\
\
n'"
).
strip
()
self
.
validate_cmd
(
"-v"
,
path
,
stdout
=
stdout
,
partial
=
True
)
def
test_double_verbose_mode
(
self
):
"""Should display detailed error information if double verbose is on."""
with
TemporaryPyFile
(
SOURCE_CODES
[
"nannynag_errored"
])
as
path
:
stdout
=
textwrap
.
dedent
(
"offending line: '
\
\
tprint(
\
"
world
\
"
)
\
\
n'"
).
strip
()
self
.
validate_cmd
(
"-vv"
,
path
,
stdout
=
stdout
,
partial
=
True
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment