Skip to content

Fixed Django tests discovery #21468

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

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions pythonFiles/testing_tools/unittest_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,27 @@
import traceback
import unittest

import os.path

sys.path.insert(
1,
os.path.dirname( # pythonFiles
os.path.dirname( # pythonFiles/testing_tools
os.path.abspath(__file__) # this file
)
),
)

from unittestadapter.django_test_init import setup_django_test_env

start_dir = sys.argv[1]
pattern = sys.argv[2]
top_level_dir = sys.argv[3] if len(sys.argv) >= 4 else None
sys.path.insert(0, os.getcwd())

# Setup django env to prevent missing django tests
setup_django_test_env(start_dir)


def get_sourceline(obj):
try:
Expand Down
4 changes: 4 additions & 0 deletions pythonFiles/unittestadapter/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

# If I use from utils then there will be an import error in test_discovery.py.
from unittestadapter.utils import TestNode, build_test_tree, parse_unittest_args
from unittestadapter.django_test_init import setup_django_test_env

from typing_extensions import NotRequired, TypedDict, Literal

Expand Down Expand Up @@ -113,6 +114,9 @@ def discover_tests(

start_dir, pattern, top_level_dir = parse_unittest_args(argv[index + 1 :])

# Setup django env to prevent missing django tests
setup_django_test_env(start_dir)

# Perform test discovery.
port, uuid = parse_discovery_cli_args(argv[:index])
payload = discover_tests(start_dir, pattern, top_level_dir, uuid)
Expand Down
55 changes: 55 additions & 0 deletions pythonFiles/unittestadapter/django_test_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""
This module sets up a Django environment to run Django tests.
"""

import os
import re
import sys


def setup_django_test_env(workspace_directory="."):
"""Configures the Django environment for running Django tests.

If Django is not installed, workspace_directory is not in sys.path or
manage.py can not be found inside the given workspace_directory, the function fails quietly.

Args:
workspace_directory (str): The current workspace directory that is expected to contain manage.py module

Returns:
None
"""

# To avoid false positive ModuleNotFoundError from django.setup() due to missing current workspace in sys.path
sys.path.insert(0, os.getcwd())

try:
import django
except ImportError:
return

manage_py_module = os.path.join(workspace_directory, "manage.py")
if not os.path.exists(manage_py_module):
return

dj_settings_module = None

with open(manage_py_module, "r") as manage_py:
pattern = r"^os\.environ\.setdefault\((\'|\")DJANGO_SETTINGS_MODULE(\'|\"), (\'|\")(?P<settings_path>[\w.]+)(\'|\")\)$"
for line in manage_py.readlines():
match_result = re.match(pattern, line.strip())
if match_result is not None:
dj_settings_module = match_result.groupdict().get("settings_path", None)
break

if dj_settings_module is None:
return

os.environ.setdefault("DJANGO_SETTINGS_MODULE", dj_settings_module)

try:
django.setup()
except ModuleNotFoundError:
return

return
4 changes: 4 additions & 0 deletions pythonFiles/unittestadapter/execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from testing_tools import process_json_util, socket_manager
from unittestadapter.utils import parse_unittest_args
from unittestadapter.django_test_init import setup_django_test_env

DEFAULT_PORT = "45454"

Expand Down Expand Up @@ -259,6 +260,9 @@ def send_run_data(raw_data, port, uuid):

start_dir, pattern, top_level_dir = parse_unittest_args(argv[index + 1 :])

# Setup django env to prevent missing django tests
setup_django_test_env(start_dir)

run_test_ids_port = os.environ.get("RUN_TEST_IDS_PORT")
run_test_ids_port_int = (
int(run_test_ids_port) if run_test_ids_port is not None else 0
Expand Down
7 changes: 7 additions & 0 deletions pythonFiles/visualstudio_py_testlauncher.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
import traceback
import unittest

sys.path.insert(1, os.path.abspath(__file__)) # this file

from unittestadapter.django_test_init import setup_django_test_env

try:
import thread
except:
Expand Down Expand Up @@ -276,6 +280,9 @@ def main():
)
(opts, _) = parser.parse_args()

# Setup django env to prevent missing django tests
setup_django_test_env(getattr(opts, "us", ".") or ".")

sys.path[0] = os.getcwd()
if opts.result_port:
try:
Expand Down