Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit96cc739

Browse files
authored
Merge pull request#1341 from tminka/TestPythonTest
Python tests can now be debugged by running them as embedded tests within NUnitFixed import hook replacing import error message
2 parents107c8b9 +4ac44fe commit96cc739

File tree

6 files changed

+142
-2
lines changed

6 files changed

+142
-2
lines changed

‎.github/workflows/main.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,13 @@ jobs:
4949
-name:Python Tests
5050
run:pytest
5151

52-
-name:RunEmbedding tests
52+
-name:Embedding tests
5353
run:dotnet test --runtime any-${{ matrix.platform }} src/embed_tests/
5454
if:${{ matrix.os != 'macos' }}# Not working right now, doesn't find libpython
5555

56+
-name:Python tests run from .NET
57+
run:dotnet test --runtime any-${{ matrix.platform }} src/python_tests_runner/
58+
if:${{ matrix.os == 'windows' }}# Not working for others right now
59+
5660
# TODO: Run perf tests
5761
# TODO: Run mono tests on Windows?

‎CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ details about the cause of the failure
4444
- Made it possible to call`ToString`,`GetHashCode`, and`GetType` on inteface objects
4545
- Fixed objects returned by enumerating`PyObject` being disposed too soon
4646
- Incorrectly using a non-generic type with type parameters now produces a helpful Python error instead of throwing NullReferenceException
47+
-`import` may now raise errors with more detail than "No module named X"
4748

4849
###Removed
4950

‎pythonnet.sln

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{BC426F42
4747
tools\geninterop\geninterop.py=tools\geninterop\geninterop.py
4848
EndProjectSection
4949
EndProject
50+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") ="Python.PythonTestsRunner","src\python_tests_runner\Python.PythonTestsRunner.csproj","{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}"
51+
EndProject
5052
Global
5153
GlobalSection(SolutionConfigurationPlatforms) =preSolution
5254
Debug|Any CPU=Debug|Any CPU
@@ -129,6 +131,30 @@ Global
129131
{4F2EA4A1-7ECA-48B5-8077-7A3C366F9931}.Release|x64.Build.0=Release|x64
130132
{4F2EA4A1-7ECA-48B5-8077-7A3C366F9931}.Release|x86.ActiveCfg=Release|x86
131133
{4F2EA4A1-7ECA-48B5-8077-7A3C366F9931}.Release|x86.Build.0=Release|x86
134+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Debug|Any CPU.ActiveCfg=Debug|Any CPU
135+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Debug|Any CPU.Build.0=Debug|Any CPU
136+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Debug|x64.ActiveCfg=Debug|Any CPU
137+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Debug|x64.Build.0=Debug|Any CPU
138+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Debug|x86.ActiveCfg=Debug|Any CPU
139+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Debug|x86.Build.0=Debug|Any CPU
140+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Release|Any CPU.ActiveCfg=Release|Any CPU
141+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Release|Any CPU.Build.0=Release|Any CPU
142+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Release|x64.ActiveCfg=Release|Any CPU
143+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Release|x64.Build.0=Release|Any CPU
144+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Release|x86.ActiveCfg=Release|Any CPU
145+
{6CF9EEA0-F865-4536-AABA-739AE3DA971E}.Release|x86.Build.0=Release|Any CPU
146+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Debug|Any CPU.ActiveCfg=Debug|Any CPU
147+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Debug|Any CPU.Build.0=Debug|Any CPU
148+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Debug|x64.ActiveCfg=Debug|Any CPU
149+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Debug|x64.Build.0=Debug|Any CPU
150+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Debug|x86.ActiveCfg=Debug|Any CPU
151+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Debug|x86.Build.0=Debug|Any CPU
152+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Release|Any CPU.ActiveCfg=Release|Any CPU
153+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Release|Any CPU.Build.0=Release|Any CPU
154+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Release|x64.ActiveCfg=Release|Any CPU
155+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Release|x64.Build.0=Release|Any CPU
156+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Release|x86.ActiveCfg=Release|Any CPU
157+
{35CBBDEB-FC07-4D04-9D3E-F88FC180110B}.Release|x86.Build.0=Release|Any CPU
132158
EndGlobalSection
133159
GlobalSection(SolutionProperties) =preSolution
134160
HideSolutionNode =FALSE
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<ProjectSdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<ProjectReferenceInclude="..\runtime\Python.Runtime.csproj" />
9+
</ItemGroup>
10+
11+
<ItemGroup>
12+
<PackageReferenceInclude="NUnit"Version="3.*" />
13+
<PackageReferenceInclude="NUnit3TestAdapter"Version="3.*">
14+
<PrivateAssets>all</PrivateAssets>
15+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16+
</PackageReference>
17+
<PackageReferenceInclude="Microsoft.NET.Test.Sdk"Version="16.*" />
18+
<PackageReferenceInclude="Microsoft.NETFramework.ReferenceAssemblies"Condition="$(MSBuildRuntimeType) == 'Core'">
19+
<Version>1.0.0</Version>
20+
<PrivateAssets>all</PrivateAssets>
21+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
22+
</PackageReference>
23+
</ItemGroup>
24+
25+
</Project>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
usingSystem;
2+
usingSystem.Collections.Generic;
3+
usingSystem.IO;
4+
usingSystem.Linq;
5+
usingSystem.Reflection;
6+
usingSystem.Text;
7+
8+
usingNUnit.Framework;
9+
10+
usingPython.Runtime;
11+
12+
namespacePython.PythonTestsRunner
13+
{
14+
publicclassPythonTestRunner
15+
{
16+
[OneTimeSetUp]
17+
publicvoidSetUp()
18+
{
19+
PythonEngine.Initialize();
20+
}
21+
22+
[OneTimeTearDown]
23+
publicvoidDispose()
24+
{
25+
PythonEngine.Shutdown();
26+
}
27+
28+
/// <summary>
29+
/// Selects the Python tests to be run as embedded tests.
30+
/// </summary>
31+
/// <returns></returns>
32+
staticIEnumerable<string[]>PythonTestCases()
33+
{
34+
// Add the test that you want to debug here.
35+
yieldreturnnew[]{"test_enum","test_enum_standard_attrs"};
36+
yieldreturnnew[]{"test_generic","test_missing_generic_type"};
37+
}
38+
39+
/// <summary>
40+
/// Runs a test in src/tests/*.py as an embedded test. This facilitates debugging.
41+
/// </summary>
42+
/// <param name="testFile">The file name without extension</param>
43+
/// <param name="testName">The name of the test method</param>
44+
[TestCaseSource(nameof(PythonTestCases))]
45+
publicvoidRunPythonTest(stringtestFile,stringtestName)
46+
{
47+
// Find the tests directory
48+
stringfolder=typeof(PythonTestRunner).Assembly.Location;
49+
while(Path.GetFileName(folder)!="src")
50+
{
51+
folder=Path.GetDirectoryName(folder);
52+
}
53+
folder=Path.Combine(folder,"tests");
54+
stringpath=Path.Combine(folder,testFile+".py");
55+
if(!File.Exists(path))thrownewFileNotFoundException("Cannot find test file",path);
56+
57+
// We could use 'import' below, but importlib gives more helpful error messages than 'import'
58+
// https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
59+
// Because the Python tests sometimes have relative imports, the module name must be inside the tests package
60+
PythonEngine.Exec($@"
61+
import sys
62+
import os
63+
sys.path.append(os.path.dirname(r'{folder}'))
64+
sys.path.append(os.path.join(r'{folder}', 'fixtures'))
65+
import clr
66+
clr.AddReference('Python.Test')
67+
import tests
68+
module_name = 'tests.{testFile}'
69+
file_path = r'{path}'
70+
import importlib.util
71+
spec = importlib.util.spec_from_file_location(module_name, file_path)
72+
module = importlib.util.module_from_spec(spec)
73+
sys.modules[module_name] = module
74+
try:
75+
spec.loader.exec_module(module)
76+
except ImportError as error:
77+
raise ImportError(str(error) + ' when sys.path=' + os.pathsep.join(sys.path))
78+
module.{testName}()
79+
");
80+
}
81+
}
82+
}

‎src/runtime/importhook.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
291291
// We don't support them anyway
292292
returnIntPtr.Zero;
293293
}
294+
// Save the exception
295+
varoriginalException=newPythonException();
294296
// Otherwise, just clear the it.
295297
Exceptions.Clear();
296298

@@ -342,7 +344,7 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw)
342344
ManagedTypemt=tail.GetAttribute(name,true);
343345
if(!(mtisModuleObject))
344346
{
345-
Exceptions.SetError(Exceptions.ImportError,$"No module named{name}");
347+
originalException.Restore();
346348
returnIntPtr.Zero;
347349
}
348350
if(head==null)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp