tests: Do custom fnmatch-like matching.
fnmatch treats [, ] and ? as shell metacharacters too, and has no way to escape them. We need a literal [] and really only need * for filtering.
This commit is contained in:
parent
205af3737f
commit
3290048458
@ -48,3 +48,24 @@ def test_partial_compare_equal(val1, val2):
|
|||||||
])
|
])
|
||||||
def test_partial_compare_not_equal(val1, val2):
|
def test_partial_compare_not_equal(val1, val2):
|
||||||
assert not utils.partial_compare(val1, val2)
|
assert not utils.partial_compare(val1, val2)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('pattern, value, expected', [
|
||||||
|
('foo', 'foo', True),
|
||||||
|
('foo', 'bar', False),
|
||||||
|
('foo', 'Foo', False),
|
||||||
|
('foo', 'foobar', False),
|
||||||
|
('foo', 'barfoo', False),
|
||||||
|
|
||||||
|
('foo*', 'foobarbaz', True),
|
||||||
|
('*bar', 'foobar', True),
|
||||||
|
('foo*baz', 'foobarbaz', True),
|
||||||
|
|
||||||
|
('foo[b]ar', 'foobar', False),
|
||||||
|
('foo[b]ar', 'foo[b]ar', True),
|
||||||
|
|
||||||
|
('foo?ar', 'foobar', False),
|
||||||
|
('foo?ar', 'foo?ar', True),
|
||||||
|
])
|
||||||
|
def test_pattern_match(pattern, value, expected):
|
||||||
|
assert utils.pattern_match(pattern=pattern, value=value) == expected
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
"""Partial comparison of dicts/lists."""
|
"""Partial comparison of dicts/lists."""
|
||||||
|
|
||||||
|
|
||||||
import fnmatch
|
import re
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
|
|
||||||
@ -86,9 +86,19 @@ def partial_compare(val1, val2, *, indent=0):
|
|||||||
equal = abs(val1 - val2) < 0.00001
|
equal = abs(val1 - val2) < 0.00001
|
||||||
elif isinstance(val2, str):
|
elif isinstance(val2, str):
|
||||||
print_i("|======= Doing string comparison", indent)
|
print_i("|======= Doing string comparison", indent)
|
||||||
equal = fnmatch.fnmatchcase(val1, val2)
|
equal = pattern_match(pattern=val2, value=val1)
|
||||||
else:
|
else:
|
||||||
print_i("|======= Comparing via ==", indent)
|
print_i("|======= Comparing via ==", indent)
|
||||||
equal = val1 == val2
|
equal = val1 == val2
|
||||||
print_i("---> {}".format(equal), indent)
|
print_i("---> {}".format(equal), indent)
|
||||||
return equal
|
return equal
|
||||||
|
|
||||||
|
|
||||||
|
def pattern_match(*, pattern, value):
|
||||||
|
"""Do fnmatch.fnmatchcase like matching, but only with * active.
|
||||||
|
|
||||||
|
Return:
|
||||||
|
True on a match, False otherwise.
|
||||||
|
"""
|
||||||
|
re_pattern = '.*'.join(re.escape(part) for part in pattern.split('*'))
|
||||||
|
return re.fullmatch(re_pattern, value) is not None
|
||||||
|
@ -103,12 +103,13 @@ class TestWaitFor:
|
|||||||
with pytest.raises(testprocess.WaitForTimeout):
|
with pytest.raises(testprocess.WaitForTimeout):
|
||||||
pyproc.wait_for(data="foobar", timeout=100)
|
pyproc.wait_for(data="foobar", timeout=100)
|
||||||
|
|
||||||
def test_existing_message(self, pyproc):
|
@pytest.mark.parametrize('message', ['foobar', 'literal [x]'])
|
||||||
|
def test_existing_message(self, message, pyproc):
|
||||||
"""Test with a message which already passed when waiting."""
|
"""Test with a message which already passed when waiting."""
|
||||||
pyproc.code = "print('foobar')"
|
pyproc.code = "print('{}')".format(message)
|
||||||
pyproc.start()
|
pyproc.start()
|
||||||
time.sleep(0.5) # to make sure the message is printed
|
time.sleep(0.5) # to make sure the message is printed
|
||||||
pyproc.wait_for(data="foobar")
|
pyproc.wait_for(data=message)
|
||||||
|
|
||||||
def test_existing_message_previous_test(self, pyproc):
|
def test_existing_message_previous_test(self, pyproc):
|
||||||
"""Make sure the message of a previous test gets ignored."""
|
"""Make sure the message of a previous test gets ignored."""
|
||||||
|
@ -22,12 +22,13 @@
|
|||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import fnmatch
|
|
||||||
|
|
||||||
import pytestqt.plugin # pylint: disable=import-error
|
import pytestqt.plugin # pylint: disable=import-error
|
||||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QProcess, QObject, QElapsedTimer
|
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QProcess, QObject, QElapsedTimer
|
||||||
from PyQt5.QtTest import QSignalSpy
|
from PyQt5.QtTest import QSignalSpy
|
||||||
|
|
||||||
|
from helpers import utils # pylint: disable=import-error
|
||||||
|
|
||||||
|
|
||||||
class InvalidLine(Exception):
|
class InvalidLine(Exception):
|
||||||
|
|
||||||
@ -199,7 +200,7 @@ class Process(QObject):
|
|||||||
|
|
||||||
- If expected is None, the filter always matches.
|
- If expected is None, the filter always matches.
|
||||||
- If the value is a string or bytes object and the expected value is
|
- If the value is a string or bytes object and the expected value is
|
||||||
too, the pattern is treated as a fnmatch glob pattern.
|
too, the pattern is treated as a glob pattern (with only * active).
|
||||||
- If the value is a string or bytes object and the expected value is a
|
- If the value is a string or bytes object and the expected value is a
|
||||||
compiled regex, it is used for matching.
|
compiled regex, it is used for matching.
|
||||||
- If the value is any other type, == is used.
|
- If the value is any other type, == is used.
|
||||||
@ -213,7 +214,7 @@ class Process(QObject):
|
|||||||
elif isinstance(expected, regex_type):
|
elif isinstance(expected, regex_type):
|
||||||
return expected.match(value)
|
return expected.match(value)
|
||||||
elif isinstance(value, (bytes, str)):
|
elif isinstance(value, (bytes, str)):
|
||||||
return fnmatch.fnmatchcase(value, expected)
|
return utils.pattern_match(pattern=expected, value=value)
|
||||||
else:
|
else:
|
||||||
return value == expected
|
return value == expected
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user