Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make keyword expression matching case-insensitive #6316

Merged
5 changes: 3 additions & 2 deletions AUTHORS
Expand Up @@ -59,12 +59,12 @@ Christian Fetzer
Christian Neumüller
Christian Theunert
Christian Tismer
Christopher Gilling
Christoph Buelter
Christopher Dignam
Christopher Gilling
CrazyMerlyn
Cyrus Maden
Damian Skrzypczak
Dhiren Serai
Daniel Grana
Daniel Hahler
Daniel Nuri
Expand All @@ -79,6 +79,7 @@ David Szotten
David Vierra
Daw-Ran Liou
Denis Kirisov
Dhiren Serai
Diego Russo
Dmitry Dygalo
Dmitry Pribysh
Expand Down
1 change: 1 addition & 0 deletions changelog/6316.improvement.rst
@@ -0,0 +1 @@
Matching of ``-k EXPRESSION`` to test names is now case-insensitive.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we must identify this as breaking change

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We currently don't have a changelog category for that... what do you suggest @RonnyPfannschmidt?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

creating one

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. Is there something I can do here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ronny I suggest we replace "remove" by "breaking", after all every removal is a breaking change, while breaking changes are not necesserily removals

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RonnyPfannschmidt will you do it? I suggest pushing it to this PR already, it is small/trivial set of changes anyway.

If you don't have the time let me know, I can spare a few minutes to do this if necessary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicoddemus i cant get to it today, please sort it out and thanks in advance

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RonnyPfannschmidt @BeyondEvil can you guys do a final review?

4 changes: 4 additions & 0 deletions doc/en/example/markers.rst
Expand Up @@ -148,6 +148,10 @@ which implements a substring match on the test names instead of the
exact match on markers that ``-m`` provides. This makes it easy to
select tests based on their names:

.. versionadded: 5.4

The expression matching is now case-insensitive.

.. code-block:: pytest

$ pytest -v -k http # running with the above defined example module
Expand Down
4 changes: 2 additions & 2 deletions doc/en/usage.rst
Expand Up @@ -94,8 +94,8 @@ Pytest supports several ways to run and select tests from the command-line.

pytest -k "MyClass and not method"

This will run tests which contain names that match the given *string expression*, which can
include Python operators that use filenames, class names and function names as variables.
This will run tests which contain names that match the given *string expression* (case-insensitive),
which can include Python operators that use filenames, class names and function names as variables.
The example above will run ``TestMyClass.test_something`` but not ``TestMyClass.test_method_simple``.

.. _nodeids:
Expand Down
3 changes: 2 additions & 1 deletion src/_pytest/mark/__init__.py
Expand Up @@ -52,7 +52,8 @@ def pytest_addoption(parser):
"-k 'not test_method and not test_other' will eliminate the matches. "
"Additionally keywords are matched to classes and functions "
"containing extra names in their 'extra_keyword_matches' set, "
"as well as functions which have names assigned directly to them.",
"as well as functions which have names assigned directly to them. "
"The matching is case-insensitive.",
)

group._addoption(
Expand Down
10 changes: 9 additions & 1 deletion src/_pytest/mark/legacy.py
Expand Up @@ -57,7 +57,15 @@ def from_item(cls, item):
return cls(mapped_names)

def __getitem__(self, subname):
for name in self._names:
"""Return whether subname is included within stored names.

The string inclusion check is case-insensitive.

"""
subname = subname.lower()
names = (name.lower() for name in self._names)

for name in names:
if subname in name:
return True
return False
Expand Down
37 changes: 37 additions & 0 deletions testing/test_collection.py
Expand Up @@ -809,6 +809,43 @@ def test___repr__():
reprec = testdir.inline_run("-k repr")
reprec.assertoutcome(passed=1, failed=0)

def test_keyword_matching_is_case_insensitive_by_default(self, testdir):
"""Check that selection via -k EXPRESSION is case-insensitive.

Since markers are also added to the node keywords, they too can
be matched without having to think about case sensitivity.

"""
testdir.makepyfile(
"""
import pytest

def test_sPeCiFiCToPiC_1():
assert True

class TestSpecificTopic_2:
def test(self):
assert True

@pytest.mark.sPeCiFiCToPic_3
def test():
assert True

@pytest.mark.sPeCiFiCToPic_4
class Test:
def test(self):
assert True

cb109 marked this conversation as resolved.
Show resolved Hide resolved
def test_failing_5():
assert False, "This should not match"

"""
)
num_matching_tests = 4
for expression in ("specifictopic", "SPECIFICTOPIC", "SpecificTopic"):
reprec = testdir.inline_run("-k " + expression)
reprec.assertoutcome(passed=num_matching_tests, failed=0)


COLLECTION_ERROR_PY_FILES = dict(
test_01_failure="""
Expand Down