26 using System.Collections;
27 using System.Collections.Generic;
28 using System.Net.Sockets;
29 using System.Reflection;
30 using System.Threading;
31 using System.Threading.Tasks;
32 using SiliconStudio.Paradox.Graphics.Regression;
39 using MonoTouch.Foundation;
40 using MonoTouch.ObjCRuntime;
41 using MonoTouch.UIKit;
45 using MonoTouch.Dialog;
47 using NUnit.Framework.Api;
48 using NUnit.Framework.Internal;
50 using NUnit.Framework.Internal.WorkItems;
52 namespace SiliconStudio.Paradox.UnitTesting.UI {
61 TestSuite suite =
new TestSuite (String.Empty);
64 [CLSCompliant (
false)]
68 throw new ArgumentNullException (
"window");
71 filter = TestFilter.Empty;
74 public bool AutoStart {
75 get {
return TouchOptions.Current.AutoStart; }
76 set { TouchOptions.Current.AutoStart = value; }
79 public ITestFilter Filter {
80 get {
return filter; }
81 set { filter = value; }
84 public bool TerminateAfterExecution {
85 get {
return TouchOptions.Current.TerminateAfterExecution; }
86 set { TouchOptions.Current.TerminateAfterExecution = value; }
89 [CLSCompliant (
false)]
90 public UINavigationController NavigationController {
91 get {
return (UINavigationController) window.RootViewController; }
94 List<Assembly> assemblies =
new List<Assembly> ();
95 ManualResetEvent mre =
new ManualResetEvent (
false);
97 public void Add (Assembly assembly)
100 throw new ArgumentNullException (
"assembly");
102 assemblies.Add (assembly);
105 static void TerminateWithSuccess ()
107 Selector selector =
new Selector (
"terminateWithSuccess");
108 UIApplication.SharedApplication.PerformSelector (selector, UIApplication.SharedApplication, 0);
111 [CLSCompliant (
false)]
114 var menu =
new RootElement (
"Test Runner");
116 var runMode =
new Section(
"Run Mode");
117 var interactiveCheckBox =
new CheckboxElement(
"Enable Interactive Mode");
119 runMode.Add(interactiveCheckBox);
122 Section main =
new Section (
"Loading test suites...");
125 Section options =
new Section () {
126 new StyledStringElement (
"Options", Options) { Accessory = UITableViewCellAccessory.DisclosureIndicator },
127 new StyledStringElement (
"Credits", Credits) { Accessory = UITableViewCellAccessory.DisclosureIndicator }
133 ThreadPool.QueueUserWorkItem (delegate {
134 foreach (Assembly assembly
in assemblies)
135 Load (assembly, null);
137 window.InvokeOnMainThread (delegate {
139 while (suite.Tests.Count == 1 && (suite.Tests[0] is TestSuite))
140 suite = (TestSuite)suite.Tests[0];
142 foreach (TestSuite ts in suite.Tests) {
143 main.Add (Setup (ts));
148 menu.Reload (main, UITableViewRowAnimation.Fade);
150 options.Insert (0,
new StringElement (
"Run Everything", Run));
151 menu.Reload (options, UITableViewRowAnimation.Fade);
160 ThreadPool.QueueUserWorkItem (delegate {
162 window.BeginInvokeOnMainThread (delegate {
166 if (TerminateAfterExecution)
167 TerminateWithSuccess ();
176 if (!OpenWriter (
"Run Everything"))
188 NavigationController.PushViewController (TouchOptions.Current.GetViewController (),
true);
193 var title =
new MultilineElement (
"Touch.Unit Runner\nCopyright 2011-2012 Xamarin Inc.\nAll rights reserved.");
194 title.Alignment = UITextAlignment.Center;
196 var root =
new RootElement (
"Credits") {
197 new Section () { title },
199 new HtmlElement (
"About Xamarin",
"http://www.xamarin.com"),
200 new HtmlElement (
"About MonoTouch",
"http://ios.xamarin.com"),
201 new HtmlElement (
"About MonoTouch.Dialog",
"https://github.com/migueldeicaza/MonoTouch.Dialog"),
202 new HtmlElement (
"About NUnitLite",
"http://www.nunitlite.org"),
203 new HtmlElement (
"About Font Awesome",
"http://fortawesome.github.com/Font-Awesome")
208 NavigationController.PushViewController (dv,
true);
213 public TestResult Result {
get; set; }
217 static string SelectHostName (
string[] names,
int port)
219 if (names.Length == 0)
222 if (names.Length == 1)
225 object lock_obj =
new object ();
226 string result = null;
229 using (var evt =
new ManualResetEvent (
false)) {
230 for (
int i = names.Length - 1; i >= 0; i--) {
231 var name = names [i];
232 ThreadPool.QueueUserWorkItem ((v) =>
235 var client =
new TcpClient (name, port);
236 using (var writer =
new StreamWriter (client.GetStream ())) {
237 writer.WriteLine (
"ping");
247 if (failures == names.Length)
264 DateTime now = DateTime.Now;
266 if (Writer == null) {
295 Writer = Console.Out;
299 Writer.WriteLine (
"[Runner executing:\t{0}]", message);
300 Writer.WriteLine (
"[MonoTouch Version:\t{0}]", Constants.Version);
301 Writer.WriteLine (
"[Assembly:\t{0}.dll ({1} bits)]", typeof (NSObject).Assembly.GetName ().Name, IntPtr.Size * 8);
302 Writer.WriteLine (
"[GC:\t{0}{1}]", GC.MaxGeneration == 0 ?
"Boehm":
"sgen",
303 NSObject.IsNewRefcountEnabled () ?
"+NewRefCount" : String.Empty);
304 UIDevice device = UIDevice.CurrentDevice;
305 Writer.WriteLine (
"[{0}:\t{1} v{2}]", device.Model, device.SystemName, device.SystemVersion);
306 Writer.WriteLine (
"[Device Name:\t{0}]", device.Name);
307 Writer.WriteLine (
"[Device UDID:\t{0}]", UniqueIdentifier);
308 Writer.WriteLine (
"[Device Locale:\t{0}]", NSLocale.CurrentLocale.Identifier);
309 Writer.WriteLine (
"[Device Date/Time:\t{0}]", now);
311 Writer.WriteLine (
"[Bundle:\t{0}]", NSBundle.MainBundle.BundleIdentifier);
320 [System.Runtime.InteropServices.DllImport (
"/usr/lib/libobjc.dylib")]
321 static extern IntPtr objc_msgSend (IntPtr receiver, IntPtr selector);
325 static string UniqueIdentifier {
327 IntPtr handle = UIDevice.CurrentDevice.Handle;
328 if (UIDevice.CurrentDevice.RespondsToSelector (
new Selector (
"uniqueIdentifier")))
329 return NSString.FromHandle (objc_msgSend (handle, Selector.GetHandle(
"uniqueIdentifier")));
336 int total = passed + inconclusive + failed;
337 Writer.WriteLine (
"Tests run: {0} Passed: {1} Inconclusive: {2} Failed: {3} Ignored: {4}", total, passed, inconclusive, failed, ignored);
345 Dictionary<TestSuite, TouchViewController> suites_dvc =
new Dictionary<TestSuite, TouchViewController> ();
346 Dictionary<TestSuite, TestSuiteElement> suite_elements =
new Dictionary<TestSuite, TestSuiteElement> ();
347 Dictionary<TestMethod, TestCaseElement> case_elements =
new Dictionary<TestMethod, TestCaseElement> ();
349 public void Show (TestSuite suite)
351 NavigationController.PushViewController (suites_dvc [suite],
true);
356 while (suite.Tests.Count == 1 && (suite.Tests[0] is TestSuite))
357 suite = (TestSuite)suite.Tests[0];
360 suite_elements.Add (suite, tse);
362 var root =
new RootElement (
"Tests");
364 Section section =
new Section (suite.Name);
365 foreach (ITest test
in suite.Tests) {
366 TestSuite ts = (test as TestSuite);
368 section.Add (Setup (ts));
370 TestMethod tc = (test as TestMethod);
372 section.Add (Setup (tc));
374 throw new NotImplementedException (test.GetType ().ToString ());
381 if (section.Count > 1) {
382 Section options =
new Section () {
383 new StringElement (
"Run all", async delegate () {
384 if (OpenWriter (suite.Name)) {
387 suites_dvc [suite].Filter ();
394 suites_dvc.Add (suite,
new TouchViewController (root));
398 TestCaseElement Setup (TestMethod test)
400 TestCaseElement tce =
new TestCaseElement (test,
this);
401 case_elements.Add (test, tce);
407 if (test is TestSuite) {
409 Writer.WriteLine (test.Name);
415 UIApplication.SharedApplication.InvokeOnMainThread(() => UpdateTestResult(r));
420 TestResult result = r as TestResult;
421 TestSuite ts = result.Test as TestSuite;
424 if (suite_elements.TryGetValue (ts, out tse))
427 TestMethod tc = result.Test as TestMethod;
429 case_elements [tc].Update (result);
432 if (result.Test is TestSuite) {
433 if (!result.IsFailure () && !result.IsSuccess () && !result.IsInconclusive () && !result.IsIgnored ())
434 Writer.WriteLine (
"\t[INFO] {0}", result.Message);
436 string name = result.Test.Name;
437 if (!String.IsNullOrEmpty (name))
438 Writer.WriteLine (
"{0} : {1} ms", name, result.Duration.TotalMilliseconds);
440 if (result.IsSuccess ()) {
441 Writer.Write (
"\t[PASS] ");
443 }
else if (result.IsIgnored ()) {
444 Writer.Write (
"\t[IGNORED] ");
446 }
else if (result.IsFailure ()) {
447 Writer.Write (
"\t[FAIL] ");
449 }
else if (result.IsInconclusive ()) {
450 Writer.Write (
"\t[INCONCLUSIVE] ");
453 Writer.Write (
"\t[INFO] ");
455 Writer.Write (result.Test.Name);
457 string message = result.Message;
458 if (!String.IsNullOrEmpty (message)) {
459 Writer.Write (
" : {0}", message.Replace (
"\r\n",
"\\r\\n"));
463 string stacktrace = result.StackTrace;
464 if (!String.IsNullOrEmpty (result.StackTrace)) {
465 string[] lines = stacktrace.Split (
new char [] {
'\r',
'\n' }, StringSplitOptions.RemoveEmptyEntries);
466 foreach (
string line
in lines)
467 Writer.WriteLine (
"\t\t{0}", line);
472 NamespaceAssemblyBuilder builder =
new NamespaceAssemblyBuilder(
new NUnitLiteTestAssemblyBuilder());
473 Dictionary<string, object> empty =
new Dictionary<string, object> ();
477 return AddSuite (builder.Build (assemblyName, settings ?? empty));
482 return AddSuite (builder.Build (assembly, settings ?? empty));
485 bool AddSuite (TestSuite ts)
495 return Task.Run(() =>
498 TestExecutionContext current = TestExecutionContext.CurrentContext;
499 current.WorkDirectory = Environment.CurrentDirectory;
501 current.GetType().GetField(
"listener", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(current,
this);
502 current.TestObject = test is TestSuite ? null : Reflect.Construct((test as TestMethod).Method.ReflectedType, null);
503 WorkItem wi = test.CreateWorkItem(filter);
510 public ITest LoadedTest {
void Add(Assembly assembly)
bool Load(Assembly assembly, IDictionary settings)
void UpdateTestResult(ITestResult r)
bool OpenWriter(string message)
static bool ForceInteractiveMode
void TestStarted(ITest test)
TouchRunner(UIWindow window)
void TestFinished(ITestResult r)
bool Load(string assemblyName, IDictionary settings)
global::MonoTouch.Constants Constants
void TestOutput(TestOutput testOutput)
void Show(TestSuite suite)
Task< TestResult > Run(Test test)
UIViewController GetViewController()