-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTestInstrumentation.cs
More file actions
107 lines (93 loc) · 4.14 KB
/
TestInstrumentation.cs
File metadata and controls
107 lines (93 loc) · 4.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using Android.Runtime;
using Microsoft.Testing.Extensions;
using Microsoft.Testing.Platform.Builder;
using Microsoft.Testing.Platform.Extensions;
using Microsoft.Testing.Platform.Extensions.Messages;
[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]
namespace AndroidDotNetTest;
[Instrumentation(Name = "com.companyname.AndroidDotNetTest.TestInstrumentation")]
public class TestInstrumentation : Instrumentation
{
protected TestInstrumentation(IntPtr handle, JniHandleOwnership ownership)
: base(handle, ownership) { }
public override void OnCreate(Bundle? arguments)
{
base.OnCreate(arguments);
Start();
}
public override void OnStart()
{
base.OnStart();
Task.Run(async () =>
{
var consumer = new ResultConsumer(this);
var bundle = new Bundle();
try
{
var writeablePath = Application.Context.GetExternalFilesDir(null)?.AbsolutePath ?? Path.GetTempPath();
var resultsPath = Path.Combine(writeablePath, "TestResults");
var builder = await TestApplication.CreateBuilderAsync([
"--results-directory", resultsPath,
"--report-trx"
]);
builder.AddMSTest(() => [GetType().Assembly]);
builder.AddTrxReportProvider();
builder.TestHost.AddDataConsumer(_ => consumer);
using ITestApplication app = await builder.BuildAsync();
await app.RunAsync();
bundle.PutInt("passed", consumer.Passed);
bundle.PutInt("failed", consumer.Failed);
bundle.PutInt("skipped", consumer.Skipped);
bundle.PutString("resultsPath", consumer.TrxReportPath);
Finish(Result.Ok, bundle);
}
catch (Exception ex)
{
bundle.PutString("error", ex.ToString());
Finish(Result.Canceled, bundle);
}
});
}
class ResultConsumer(Instrumentation instrumentation) : IDataConsumer
{
int _passed, _failed, _skipped;
public int Passed => _passed;
public int Failed => _failed;
public int Skipped => _skipped;
public string? TrxReportPath;
public string Uid => nameof(ResultConsumer);
public string DisplayName => nameof(ResultConsumer);
public string Description => "";
public string Version => "1.0";
public Task<bool> IsEnabledAsync() => Task.FromResult(true);
public Type[] DataTypesConsumed => [typeof(TestNodeUpdateMessage), typeof(SessionFileArtifact)];
public Task ConsumeAsync(IDataProducer dataProducer, IData value, CancellationToken cancellationToken)
{
if (value is SessionFileArtifact artifact)
{
TrxReportPath = artifact.FileInfo.FullName;
}
else if (value is TestNodeUpdateMessage { TestNode: var node })
{
var state = node.Properties.SingleOrDefault<TestNodeStateProperty>();
string? outcome = state switch
{
PassedTestNodeStateProperty => "passed",
FailedTestNodeStateProperty or ErrorTestNodeStateProperty
or TimeoutTestNodeStateProperty or CancelledTestNodeStateProperty => "failed",
SkippedTestNodeStateProperty => "skipped",
_ => null
};
if (outcome is null)
return Task.CompletedTask;
_ = outcome switch { "passed" => Interlocked.Increment(ref _passed), "failed" => Interlocked.Increment(ref _failed), _ => Interlocked.Increment(ref _skipped) };
var id = node.Properties.SingleOrDefault<TestMethodIdentifierProperty>();
var b = new Bundle();
b.PutString("test", id is not null ? $"{id.Namespace}.{id.TypeName}.{id.MethodName}" : node.DisplayName);
b.PutString("outcome", outcome);
instrumentation.SendStatus(0, b);
}
return Task.CompletedTask;
}
}
}