Skip to content

Instantly share code, notes, and snippets.

@Clancey
Created October 26, 2017 01:00
Show Gist options
  • Save Clancey/4c61421e714e044c8f6a625befb5d51a to your computer and use it in GitHub Desktop.
Save Clancey/4c61421e714e044c8f6a625befb5d51a to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.IO;
using NUnitLite.Runner;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using NUnit.Framework.Api;
using NUnit.Framework.Internal;
using Path = System.IO.Path;
using Java.Interop;
using NUnitTest = NUnit.Framework.Internal.Test;
using Android.Text;
using Java.Lang;
using Android.Graphics;
using System.Threading.Tasks;
using System.IO.Compression;
namespace Xamarin.Android.NUnitLite
{
[Activity (Label = "NUnitLite runner")]
public class TestSuiteActivity : Activity
{
static readonly string [] from_cols = {"id", "passed", "failed", "ignored", "inconclusive", "result", "message"};
static readonly int [] to_ids = { Resource.Id.ResultsId, Resource.Id.ResultsPassed, Resource.Id.ResultsFailed, Resource.Id.ResultsIgnored, Resource.Id.ResultsInconclusive, Resource.Id.ResultsResult, Resource.Id.ResultsMessage };
protected bool GCAfterEachFixture {
get { return AndroidRunner.Runner.GCAfterEachFixture; }
set { AndroidRunner.Runner.GCAfterEachFixture = value; }
}
protected ITestFilter Filter {
get { return AndroidRunner.Runner.Filter; }
set { AndroidRunner.Runner.Filter = value; }
}
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
SetContentView (Resource.Layout.test_suite);
var lv = FindViewById<ListView> (Resource.Id.TestSuiteListView);
var data = new JavaList<IDictionary<string,object>> ();
UpdateData (data, lv);
var automated = this.Intent.GetBooleanExtra ("automated", false);
if (automated) {
AndroidRunner.Runner.Options.LoadFromBundle (Intent.Extras);
}
AndroidRunner.Runner.AddTestFilters (GetIncludedCategories (), GetExcludedCategories ());
UpdateFilter ();
FindViewById<TextView> (Resource.Id.RunTestsButton).Click += (o, e) => {
AndroidRunner.Runner.Run (current_test, this);
UpdateData (data, lv);
};
FindViewById<TextView> (Resource.Id.OptionsButton).Click += (o, e) => {
var intent = new Intent (this, typeof (OptionsActivity));
intent.AddFlags (ActivityFlags.NewTask);
this.StartActivityForResult (intent, (int) Result.Ok);
};
lv.ItemClick += (sender, e) => {
var item = (TestData) ((SimpleAdapter) lv.Adapter).GetItem (e.Position);
if (AndroidRunner.Suites.ContainsKey (item.Id)) {
var intent = new Intent (this, typeof (TestSuiteActivity));
intent.AddFlags (ActivityFlags.NewTask);
intent.PutExtra ("suite", item.Id);
this.StartActivityForResult (intent, (int) Result.Ok);
} else {
var intent = new Intent (this, typeof (TestResultActivity));
intent.AddFlags (ActivityFlags.NewTask);
intent.PutExtra ("test", item.Id);
this.StartActivityForResult (intent, (int) Result.Ok);
}
};
AndroidRunner.Runner.Initialized = true;
if (automated) {
System.Threading.ThreadPool.QueueUserWorkItem (delegate {
Log.Info ("NUnitLite", "NUnit automated tests started");
AndroidRunner.Runner.Run (current_test, this);
Log.Info ("NUnitLite", "NUnit automated tests completed");
Finish ();
});
}
Log.Info ("NUnitLite", "NUnit automated tests loaded.");
}
protected override void OnResume ()
{
base.OnResume ();
var lv = FindViewById<ListView> (Resource.Id.TestSuiteListView);
var data = new JavaList<IDictionary<string,object>> ();
UpdateData (data, lv);
}
[Export("RunTests")]
public bool RunTests()
{
runTests();
return true;
}
async void runTests()
{
try{
await Task.Run(()=>{
isRunning = true;
var startTime = DateTime.Now;
var resultsXml = new NUnit2XmlOutputWriter (startTime);
var testResult = AndroidRunner.Runner.Run (current_test, this);
resultsFile = Path.GetTempFileName ();
resultsXml.WriteResultFile (testResult, resultsFile);
});
} catch (System.Exception exc) {
hadError = true;
runningError = exc.ToString();
}
finally{
isRunning = false;
}
}
bool isRunning;
bool hadError;
string runningError;
string resultsFile;
[Export("IsRunning")]
public bool IsRunning ()
{
return isRunning;
}
[Export("TestRunSuccess")]
public bool TestRunSuccess ()
{
return !hadError && !string.IsNullOrWhiteSpace(resultsFile);
}
[Export("TestResults")]
public string TestResults()
{
var bytes = File.ReadAllBytes(resultsFile);
using (var compressIntoMs = new MemoryStream())
{
using (var gzs = new GZipStream(compressIntoMs,CompressionMode.Compress))
{
gzs.Write(bytes, 0, bytes.Length);
}
var b = compressIntoMs.ToArray();
return System.Convert.ToBase64String(b);
}
}
protected virtual IEnumerable <string> GetIncludedCategories ()
{
return null;
}
protected virtual IEnumerable <string> GetExcludedCategories ()
{
return null;
}
// Subclasses can override this method to update the test filtering that the runner will use.
// Subclasses should set the `Filter` property to their new filter value
protected virtual void UpdateFilter ()
{
}
public void AddTest (Assembly assembly)
{
AndroidRunner.Runner.AddTest (assembly);
}
IEnumerable<NUnitTest> GetChildTests (NUnitTest test)
{
if (test is TestSuite)
foreach (NUnitTest child in ((TestSuite) test).Tests)
yield return child;
else
yield return test;
}
void UpdateData (JavaList<IDictionary<string,object>> data, ListView lv)
{
data.Clear ();
var testTarget = SetupTestTarget ();
foreach (var test in GetChildTests (testTarget)) {
TestResult res;
AndroidRunner.Results.TryGetValue (test.FullName, out res);
if (test is TestSuite) {
var suite = test as TestSuite;
data.Add (new TestData (suite.FullName,
res != null && res.PassCount > 0 ? res.PassCount + " passed" : null,
res != null && res.FailCount > 0 ? res.FailCount + " failed" : null,
res != null && res.SkipCount > 0 ? res.SkipCount + " ignored" : null,
res != null && res.InconclusiveCount > 0 ? res.InconclusiveCount + " inconclusive" : null,
res == null ? null : res.ResultState.Status.ToString (), res == null ? null : res.Message));
} else if (test is NUnitTest)
data.Add (new TestData (test.FullName, null, null, null, null, res == null ? null : res.ResultState.Status.ToString (), res == null ? null : res.Message));
}
lv.Adapter = new TestDataAdapter (this, data, Resource.Layout.results, from_cols, to_ids);
}
class TestDataAdapter : SimpleAdapter
{
JavaList<IDictionary<string,object>> data;
public TestDataAdapter (Context ctx, JavaList<IDictionary<string,object>> data, int resId, string [] fromCols, int [] toIds)
: base (ctx, data, resId, fromCols, toIds)
{
this.data = data;
}
public override View GetView (int position, View convertView, ViewGroup parent)
{
var view = base.GetView (position, convertView, parent);
var tv = view.FindViewById<TextView> (Resource.Id.ResultsResult);
TestStatus status;
System.Enum.TryParse<TestStatus> ((string) data [position] ["result"], out status);
tv.SetTextColor (GetStatusColor (status));
return view;
}
static Color GetStatusColor (TestStatus status)
{
switch (status) {
case TestStatus.Passed:
return Color.Green;
case TestStatus.Failed:
return Color.Red;
case TestStatus.Skipped:
return Color.Yellow;
case TestStatus.Inconclusive:
return Color.Blue;
default:
return Color.White;
}
}
}
class TestData : JavaDictionary<string,object>
{
public TestData (string id, string passed, string failed, string ignored, string inconclusive, string result, string message)
{
Id = id;
Passed = passed;
Failed = failed;
Ignored = ignored;
Inconclusive = inconclusive;
Result = result;
Message = message;
}
public string Id {
get { return (string) this ["id"]; }
set { this ["id"] = value; }
}
public string Passed {
get { return (string) this ["passed"]; }
set { this ["passed"] = value; }
}
public string Failed {
get { return (string) this ["failed"]; }
set { this ["failed"] = value; }
}
public string Ignored {
get { return (string) this ["ignored"]; }
set { this ["ignored"] = value; }
}
public string Inconclusive {
get { return (string) this ["inconclusive"]; }
set { this ["inconclusive"] = value; }
}
public string Result {
get { return (string) this ["result"]; }
set { this ["result"] = value; }
}
public string Message {
get { return (string) this ["message"]; }
set { this ["message"] = value; }
}
}
NUnitTest current_test;
NUnitTest SetupTestTarget ()
{
if (current_test == null)
current_test = AndroidRunner.GetSetupTestTarget (Intent);
return current_test;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment