microsoft / vscode-python

Python extension for Visual Studio Code
https://aka.ms/pvsc-marketplace
MIT License
4.29k stars 1.17k forks source link

Test discovery fails using unittest when there's a dot (.) in the name of the file besides the extension #8490

Closed markdall closed 4 years ago

markdall commented 4 years ago

I did search so I apologize if this is a dupe and I just missed it. I was following the tutorial here https://github.com/mjhea0/flaskr-tdd when I found that I couldn't get test discovery to work.

Environment data

Expected behavior

It finds the tests.

Actual behaviour

It doesn't find the tests.

Steps to reproduce:

  1. Name a file app.test.py, put one or more tests in it using unittest.
  2. Run Python: Configure Tests from vscode.
  3. Choose unittest, and then any of the match patterns such as *test*.py. Bonus:
  4. Rename app.test.py to app_test.py and try again. Voila, it works as expected. You can go back and forth renaming it to app.test.py to make it fail again.

Logs

Output for Python in the Output panel (View→Output, change the drop-down the upper-right of the Output panel to Python)

> d:\code\mda_flaskr_tdd\env\Scripts\python.exe -c "
import unittest
loader = unittest.TestLoader()
suites = loader.discover("./tests", pattern="*test*.py")
print("start") #Don't remove this line
for suite in suites._tests:
    for cls in suite._tests:
        try:
            for m in cls._tests:
                print(m.id())
        except:
            pass"
cwd: d:\code\mda_flaskr_tdd
> d:\code\mda_flaskr_tdd\env\Scripts\python.exe c:\Users\markd\.vscode\extensions\ms-python.python-2019.10.44104\pythonFiles\visualstudio_py_testlauncher.py --us=./tests --up=*test*.py --uvInt=2 --result-port=51428
cwd: d:\code\mda_flaskr_tdd

Output from Console under the Developer Tools panel (toggle Developer Tools on under Help; turn on source maps to make any tracebacks be useful by running Enable source map support for extension debugging)

nfo Python Extension: 2019-11-09 09:08:35: Rule = cachedInterpreters, result = runNextRule
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: Executing next rule from cachedInterpreters
3console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: autoSelectInterpreter, Class name = f, completed in 37ms, Arg 1: undefined, Return Value: undefined
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: parseEnvironmentOutput, Class name = _, completed in 0ms
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: getActivatedEnvironmentVariables, Class name = _, completed in 124ms, Arg 1: <Uri:d:\code\mda_flaskr_tdd>, Arg 2: undefined, Arg 3: undefined
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: > d:\code\mda_flaskr_tdd\env\Scripts\python.exe -c "import unittestloader = unittest.TestLoader()suites = loader.discover("./tests", pattern="*test*.py")print("start") #Don't remove this linefor suite in suites._tests:    for cls in suite._tests:        try:            for m in cls._tests:                print(m.id())        except:            pass"
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: cwd: d:\code\mda_flaskr_tdd
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: Interpreters returned by PipEnvService are of count 0
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: Interpreters returned by PipEnvService are []
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: Interpreters returned by WorkspaceVirtualEnvService are of count 1
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: Interpreters returned by WorkspaceVirtualEnvService are [{"architecture":3,"path":"d:\\code\\mda_flaskr_tdd\\env\\Scripts\\python.exe","version":{"options":{"loose":false,"includePrerelease":false},"loose":false,"raw":"3.8.0-final","major":3,"minor":8,"patch":0,"prerelease":["final"],"build":[],"version":"3.8.0-final"},"sysPrefix":"d:\\code\\mda_flaskr_tdd\\env","fileHash":"e6bce0eaf2bdda4f81186c542f047acb171520d2f274b876804fa7849965805e629f4687b9a70a160ce080c4d4c3d6052c8132d97912e4cdd20c83c6d32d191f","envName":"env","type":"Venv"}]
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: setGlobalInterpreter, Class name = f, completed in 23ms, Arg 1: {"architecture":3,"path":"C:\\Python38\\python.exe","version":{"options":{"loose":false,"includePrerelease":false},"loose":false,"raw":"3.8.0-final","major":3,"minor":8,"patch":0,"prerelease":["final"],"build":[],"version":"3.8.0-final"},"sysPrefix":"C:\\Python38","fileHash":"6f54cd746c343ba86bbaab87574cf4c2f6cbf2222f1a57766b01f10be776a882a21255d0cdf0db0731d29aae889a55366eabacbaa15b088df44fa9802e6128f2","companyDisplayName":"Python Software Foundation","type":"Unknown","displayName":"Python 3.8.0 64-bit"}, Arg 2: undefined, Return Value: false
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: Rule = system, result = runNextRule
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: Executing next rule from system
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: autoSelectInterpreter, Class name = f, completed in 50ms, Arg 1: undefined, Return Value: undefined
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: Checking whether locactors have completed locating, Class name = p, completed in 0ms, , Return Value: true
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: Hide locator refreshing progress, Class name = p, completed in 0ms, , Return Value: undefined
console.ts:137 [Extension Host] Info Python Extension: 2019-11-09 09:08:35: All locators have completed locating, Class name = p, completed in 1ms, , Return Value: undefined
brettcannon commented 4 years ago

Thanks for the bug report! We just wanted to quickly acknowledge we received it and we will triage this as soon as we can.

kimadeline commented 4 years ago

Hi @markdall 👋 Thank you for reaching out. The behaviour you've encountered is intentional because . are used as structure markers:

import unittest

class TestStringMethods(unittest.TestCase):
    def test_upper(self):
        self.assertEqual("foo".upper(), "FOO")

    def test_isupper(self):
        self.assertTrue("FOO".isupper())
        self.assertFalse("Foo".isupper())

    def test_split(self):
        s = "hello world"
        self.assertEqual(s.split(), ["hello", "world"])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

Ran 3 tests in 0.000s

OK



Having a file named `app.test.py` throws a wrench in the structure, hence why discovery fails.