Permalink
Browse files

Refactored options and test result processors.

Added tcp writer.
Added some ConfigureAwait to give more responsiveness.
  • Loading branch information...
1 parent e443796 commit fe653db55112dc68d043ad93d137d721b7b1f05d @roubachof roubachof committed Mar 4, 2016
@@ -37,7 +37,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
+ <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
+ <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=1256596694514F41A4D79DB082E50E51/@KeyIndexDefined">True</s:Boolean>
@@ -21,6 +21,8 @@
// ***********************************************************************
using System.Reflection;
+
+using NUnit.Runner.Services;
using NUnit.Runner.View;
using NUnit.Runner.ViewModel;
using Xamarin.Forms;
@@ -65,22 +67,12 @@ public void AddTestAssembly(Assembly testAssembly)
}
/// <summary>
- /// If True, the tests will run automatically when the app starts
- /// otherwise you must run them manually.
+ /// User options for the test suite.
/// </summary>
- public bool AutoRun
+ public TestOptions Options
{
- get { return _model.AutoRun; }
- set { _model.AutoRun = value; }
- }
-
- /// <summary>
- /// Creates a NUnit Xml result file on the host file system.
- /// </summary>
- public bool CreateXmlResultFile
- {
- get { return _model.CreateXmlResultFile; }
- set { _model.CreateXmlResultFile = value; }
- }
+ get { return _model.Options; }
+ set { _model.Options = value; }
+ }
}
}
@@ -0,0 +1,108 @@
+// ***********************************************************************
+// Copyright (c) 2008 Charlie Poole
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+// ***********************************************************************
+
+using System;
+using System.IO;
+
+using System.Threading.Tasks;
+
+#if NETFX_CORE
+using Windows.Networking;
+using Windows.Networking.Sockets;
+#else
+using System.Net.Sockets;
+#endif
+
+namespace NUnit.Runner.Services
+{
+ /// <summary>
+ /// Redirects output to a Tcp connection
+ /// </summary>
+ class TcpWriter : TextWriter
+ {
+ private readonly string hostName;
+ private readonly int port;
+
+ private StreamWriter writer;
+
+ public TcpWriter(string hostName, int port)
+ {
+ if (string.IsNullOrWhiteSpace(hostName))
+ {
+ throw new ArgumentNullException(nameof(hostName));
+ }
+
+ if ((port < 0) || (port > ushort.MaxValue))
+ {
+ throw new ArgumentException(nameof(port));
+ }
+
+ this.hostName = hostName;
+ this.port = port;
+ }
+
+ public async Task Connect()
+ {
+#if NETFX_CORE
+ var socket = new StreamSocket();
+ await
+ socket.ConnectAsync(new HostName(hostName), port.ToString())
+ .AsTask()
+ .ContinueWith(@object => writer = new StreamWriter(socket.OutputStream.AsStreamForWrite()));
+#else
+ TcpClient client;
+ NetworkStream stream;
+ await Task.Run(
+ () =>
+ {
+ client = new TcpClient(hostName, port);
+ stream = client.GetStream();
+ this.writer = new StreamWriter(stream);
+ }).ConfigureAwait(false);
+#endif
+ }
+
+ public override void Write(char value)
+ {
+ writer.Write(value);
+ }
+
+ public override void Write(string value)
+ {
+ writer.Write(value);
+ }
+
+ public override void WriteLine(string value)
+ {
+ writer.WriteLine(value);
+ writer.Flush();
+ }
+
+ public override System.Text.Encoding Encoding => System.Text.Encoding.UTF8;
+
+ protected override void Dispose(bool disposing)
+ {
+ writer?.Dispose();
+ }
+ }
+}
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NUnit.Runner.Services
+{
+ public class TcpWriterInfo : IEquatable<TcpWriterInfo>
+ {
+ public TcpWriterInfo(string hostName, int port)
+ {
+ if (string.IsNullOrWhiteSpace(hostName))
+ {
+ throw new ArgumentNullException(nameof(hostName));
+ }
+
+ if ((port < 0) || (port > ushort.MaxValue))
+ {
+ throw new ArgumentException(nameof(port));
+ }
+
+ this.Hostname = hostName;
+ this.Port = port;
+ }
+
+ public string Hostname { get; set; }
+
+ public int Port { get; set; }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <returns>
+ /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
+ /// </returns>
+ /// <param name="other">An object to compare with this object.</param>
+ public bool Equals(TcpWriterInfo other)
+ {
+ return Hostname.Equals(other.Hostname, StringComparison.OrdinalIgnoreCase) && Port == other.Port;
+ }
+
+ public override string ToString()
+ {
+ return $"{Hostname}:{Port}";
+ }
+ }
+}
@@ -0,0 +1,46 @@
+using System;
+using System.Diagnostics;
+using System.Threading.Tasks;
+
+using NUnit.Framework.Interfaces;
+
+namespace NUnit.Runner.Services
+{
+ public class TcpWriterProcessor : TestResultProcessor
+ {
+ public TcpWriterProcessor(TestOptions options)
+ : base(options)
+ {
+ }
+
+ public override async Task Process(ITestResult testResult)
+ {
+ if (Options.TcpWriterParamaters != null)
+ {
+ try
+ {
+ await WriteResult(testResult);
+ }
+ catch (Exception exception)
+ {
+ string message = $"Fatal error while trying to send xml result by TCP to {Options.TcpWriterParamaters}\nDoes your server is running ?";
+ throw new InvalidOperationException(message, exception);
+ }
+ }
+
+ if (Successor != null)
+ {
+ await Successor.Process(testResult);
+ }
+ }
+
+ private async Task WriteResult(ITestResult testResult)
+ {
+ using (var tcpWriter = new TcpWriter(Options.TcpWriterParamaters.Hostname, Options.TcpWriterParamaters.Port))
+ {
+ await tcpWriter.Connect().ConfigureAwait(false);
+ tcpWriter.Write(testResult.ToXml(true).OuterXml);
+ }
+ }
+ }
+}
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace NUnit.Runner.Services
+{
+ /// <summary>
+ /// Options for the device test suite.
+ /// </summary>
+ public class TestOptions
+ {
+ /// <summary>
+ /// If True, the tests will run automatically when the app starts
+ /// otherwise you must run them manually.
+ /// </summary>
+ public bool AutoRun { get; set; }
+
+ /// <summary>
+ /// Information about the tcp listener host and port.
+ /// For now, send result as XML to the listening server.
+ /// </summary>
+ public TcpWriterInfo TcpWriterParamaters { get; set; }
+
+ /// <summary>
+ /// Creates a NUnit Xml result file on the host file system using PCLStorage library.
+ /// </summary>
+ public bool CreateXmlResultFile { get; set; }
+ }
+}
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+using NUnit.Framework.Interfaces;
+
+namespace NUnit.Runner.Services
+{
+ public abstract class TestResultProcessor
+ {
+ protected TestResultProcessor(TestOptions options)
+ {
+ Options = options;
+ }
+
+ protected TestOptions Options { get; private set; }
+
+ public TestResultProcessor Successor { get; set; }
+
+ public abstract Task Process(ITestResult testResult);
+
+ public static TestResultProcessor BuildChainOfResponsability(TestOptions options)
+ {
+ var tcpWriter = new TcpWriterProcessor(options);
+ var xmlFileWriter = new XmlFileProcessor(options);
+
+ tcpWriter.Successor = xmlFileWriter;
+ return tcpWriter;
+ }
+ }
+}
@@ -0,0 +1,64 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Threading.Tasks;
+
+using NUnit.Framework.Interfaces;
+
+using PCLStorage;
+
+using FileAccess = PCLStorage.FileAccess;
+
+namespace NUnit.Runner.Services
+{
+ public class XmlFileProcessor : TestResultProcessor
+ {
+ public XmlFileProcessor(TestOptions options)
+ : base(options)
+ {
+ }
+
+ public override async Task Process(ITestResult testResult)
+ {
+ if (Options.CreateXmlResultFile)
+ {
+ try
+ {
+ await WriteXmlResultFile(testResult).ConfigureAwait(false);
+ }
+ catch (Exception)
+ {
+ Debug.WriteLine("Fatal error while trying to write xml result file!");
+ throw;
+ }
+ }
+
+ if (Successor != null)
+ {
+ await Successor.Process(testResult).ConfigureAwait(false);
+ }
+ }
+
+ private async Task WriteXmlResultFile(ITestResult testResult)
+ {
+ const string OutputFolderName = "NUnitTestsOutput";
+ const string OutputXmlReportName = "nunit_result.xml";
+ var localStorageFolder = FileSystem.Current.LocalStorage;
+
+ var existResult = await localStorageFolder.CheckExistsAsync(OutputFolderName);
+ if (existResult == ExistenceCheckResult.FileExists)
+ {
+ var existingFile = await localStorageFolder.GetFileAsync(OutputFolderName);
+ await existingFile.DeleteAsync();
+ }
+
+ var outputFolder = await localStorageFolder.CreateFolderAsync(OutputFolderName, CreationCollisionOption.OpenIfExists);
+ IFile xmlResultFile = await outputFolder.CreateFileAsync(OutputXmlReportName, CreationCollisionOption.ReplaceExisting);
+ using (var resultFileStream = new StreamWriter(await xmlResultFile.OpenAsync(FileAccess.ReadAndWrite)))
+ {
+ string xmlString = testResult.ToXml(true).OuterXml;
+ await resultFileStream.WriteAsync(xmlString);
+ }
+ }
+ }
+}
Oops, something went wrong.

0 comments on commit fe653db

Please sign in to comment.