Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5bb2566

Browse files
committed
Python tests can now be debugged by running them as embedded tests within NUnit.
Added PythonTestsRunner project and extra build actions.
1 parent 107c8b9 commit 5bb2566

File tree

4 files changed

+138
-1
lines changed

4 files changed

+138
-1
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: Run Embedding 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 runner
57+
run: dotnet test --runtime any-${{ matrix.platform }} src/python_tests_runner/
58+
if: ${{ matrix.os != 'macos' }} # Not working right now, doesn't find libpython
59+
5660
# TODO: Run perf tests
5761
# TODO: Run mono tests on Windows?

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+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<ProjectReference Include="..\runtime\Python.Runtime.csproj" />
9+
</ItemGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="NUnit" Version="3.*" />
13+
<PackageReference Include="NUnit3TestAdapter" Version="3.*">
14+
<PrivateAssets>all</PrivateAssets>
15+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16+
</PackageReference>
17+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.*" />
18+
<PackageReference Include="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+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Reflection;
6+
using System.Text;
7+
8+
using NUnit.Framework;
9+
10+
using Python.Runtime;
11+
12+
namespace Python.PythonTestsRunner
13+
{
14+
public class PythonTestRunner
15+
{
16+
[OneTimeSetUp]
17+
public void SetUp()
18+
{
19+
PythonEngine.Initialize();
20+
}
21+
22+
[OneTimeTearDown]
23+
public void Dispose()
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+
static IEnumerable<string[]> PythonTestCases()
33+
{
34+
// Add the test that you want to debug here.
35+
yield return new[] { "test_enum", "test_enum_standard_attrs" };
36+
yield return new[] { "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+
public void RunPythonTest(string testFile, string testName)
46+
{
47+
// Find the tests directory
48+
string folder = typeof(PythonTestRunner).Assembly.Location;
49+
while (Path.GetFileName(folder) != "src")
50+
{
51+
folder = Path.GetDirectoryName(folder);
52+
}
53+
folder = Path.Combine(folder, "tests");
54+
string path = Path.Combine(folder, testFile + ".py");
55+
if (!File.Exists(path)) throw new FileNotFoundException("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+
}

0 commit comments

Comments
 (0)