Created
December 22, 2015 21:14
-
-
Save miklund/59ee458eaa75fbf2973f to your computer and use it in GitHub Desktop.
2009-03-24 Run your unit tests on the web
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Title: Run your unit tests on the web | |
Author: Mikael Lundin | |
Link: http://blog.mikaellundin.name/2009/03/24/run-your-unit-tests-on-the-web.html |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<litemedia:UnitTestDataSource runat="server" ID="UnitTestDataSource" AssemblyName="LiteMedia.Mint.UnitTests" OnLoad="DataBind" /> | |
<asp:Repeater runat="server" DataSourceID="UnitTestDataSource" OnLoad="DataBind"> | |
<HeaderTemplate><ul></HeaderTemplate> | |
<ItemTemplate> | |
<li class="<%# GetSuccessClass(Container.DataItem) %>"> | |
<span class="name"><%# Container.DataItem %></span> | |
<p class="exception <%# GetSuccessClass(Container.DataItem) %>"> | |
<%# GetException(Container.DataItem) %> | |
</p> | |
</li> | |
</ItemTemplate> | |
<FooterTemplate></ul></FooterTemplate> | |
</asp:Repeater> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// <copyright file="UnitTestDataSource.cs" company="LiteMedia"> | |
// Copy freely and buy me a beer! | |
// </copyright> | |
// <author>Mikael Lundin</author> | |
// <email>[email protected]</email> | |
// <date>2009-03-24</date> | |
// <summary>This UnitTestDataSource will help you to run your unit tests in a web application and validate the result.</summary> | |
namespace Litemedia.Utils.Web | |
{ | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Reflection; | |
using System.Web.UI; | |
using NUnit.Framework; | |
/// <summary> | |
/// This datasource control may be put on any ASPX page and serve as a datasource for other controls | |
/// </summary> | |
public class UnitTestDataSource : DataSourceControl | |
{ | |
/// <summary> | |
/// Gets or sets the name of the assembly containing the tests | |
/// </summary> | |
/// <value>The name of the assembly.</value> | |
public string AssemblyName { get; set; } | |
/// <summary> | |
/// Gets the named data source view associated with the data source control. | |
/// </summary> | |
/// <param name="viewName">The name of the <see cref="T:System.Web.UI.DataSourceView"/> to retrieve. In data source controls that support only one view, such as <see cref="T:System.Web.UI.WebControls.SqlDataSource"/>, this parameter is ignored.</param> | |
/// <returns> | |
/// Returns the named <see cref="T:System.Web.UI.DataSourceView"/> associated with the <see cref="T:System.Web.UI.DataSourceControl"/>. | |
/// </returns> | |
protected override DataSourceView GetView(string viewName) | |
{ | |
return new NUnitTestDataSourceView(this, viewName, this.AssemblyName); | |
} | |
} | |
/// <summary> | |
/// This is a NUnit test runner, that will find all test methods in an assembly and run them | |
/// </summary> | |
public class NUnitTestDataSourceView : DataSourceView | |
{ | |
/// <summary> | |
/// This is the assembly that contains the unit tests | |
/// </summary> | |
private Assembly assembly; | |
/// <summary> | |
/// Initializes a new instance of the <see cref="NUnitTestDataSourceView"/> class. | |
/// </summary> | |
/// <param name="owner">The datasource owner</param> | |
/// <param name="viewName">Name of the view.</param> | |
/// <param name="assemblyName">Name of the assembly where the tests are located</param> | |
public NUnitTestDataSourceView(IDataSource owner, string viewName, string assemblyName) | |
: base(owner, viewName) | |
{ | |
this.assembly = Assembly.Load(assemblyName); | |
} | |
/// <summary> | |
/// Gets a list of data from the underlying data storage. | |
/// </summary> | |
/// <param name="arguments">A <see cref="T:System.Web.UI.DataSourceSelectArguments"/> that is used to request operations on the data beyond basic data retrieval.</param> | |
/// <returns> | |
/// An <see cref="T:System.Collections.IEnumerable"/> list of data from the underlying data storage. | |
/// </returns> | |
protected override IEnumerable ExecuteSelect(DataSourceSelectArguments arguments) | |
{ | |
List<UnitTestResult> result = new List<UnitTestResult>(); | |
foreach (Type type in this.GetAllTestFixtures()) | |
{ | |
object instance = Activator.CreateInstance(type); | |
foreach (var method in this.GetAllMethods(type)) | |
{ | |
string name = string.Format("{0}.{1}.{2}()", type.Namespace, type.Name, method.Name); | |
try | |
{ | |
if (this.HasAttribute(method, typeof(IgnoreAttribute))) | |
{ | |
continue; // IgnoreAttribute, casues this test not to rune | |
} | |
method.Invoke(instance, new object[] { }); | |
result.Add(new UnitTestResult(name)); // Success! | |
} | |
catch (Exception outerException) | |
{ | |
Exception innerException = outerException.InnerException; | |
if (this.IsExpectedException(method, innerException)) | |
{ | |
result.Add(new UnitTestResult(name)); // Success! | |
} | |
else | |
{ | |
result.Add(new UnitTestResult(name, innerException)); // Failure! | |
} | |
} | |
} | |
} | |
return result; | |
} | |
/// <summary> | |
/// Determines whether the specified member has attribute. | |
/// </summary> | |
/// <param name="member">The member.</param> | |
/// <param name="attributeType">Type of the attribute.</param> | |
/// <returns> | |
/// <c>true</c> if the specified member has attribute; otherwise, <c>false</c>. | |
/// </returns> | |
private bool HasAttribute(MemberInfo member, Type attributeType) | |
{ | |
return member.GetCustomAttributes(attributeType, true).Length > 0; | |
} | |
/// <summary> | |
/// Gets all test fixtures in the assembly. | |
/// </summary> | |
/// <returns>A list of types that are marked with the TestFixtureAttribute</returns> | |
private IEnumerable<Type> GetAllTestFixtures() | |
{ | |
IList<Type> types = new List<Type>(); | |
foreach (Type type in this.assembly.GetTypes()) | |
{ | |
if (this.HasAttribute(type, typeof(TestFixtureAttribute))) | |
{ | |
types.Add(type); | |
} | |
} | |
return types; | |
} | |
/// <summary> | |
/// Gets all methods with the TestAttribute | |
/// </summary> | |
/// <param name="type">The type in where we will find the methods</param> | |
/// <returns>A list of MethodInfos that are marked with the TestAttribute</returns> | |
private IEnumerable<MethodInfo> GetAllMethods(Type type) | |
{ | |
IList<MethodInfo> methods = new List<MethodInfo>(); | |
foreach (MethodInfo method in type.GetMethods()) | |
{ | |
if (this.HasAttribute(method, typeof(TestAttribute))) | |
{ | |
methods.Add(method); | |
} | |
} | |
return methods; | |
} | |
/// <summary> | |
/// Determines whether [is expected exception] [the specified method]. | |
/// </summary> | |
/// <param name="method">The method that threw the exception</param> | |
/// <param name="e">The exception that was thrown</param> | |
/// <returns> | |
/// <c>true</c> if [is expected exception] [the specified method]; otherwise, <c>false</c>. | |
/// </returns> | |
private bool IsExpectedException(MethodInfo method, Exception e) | |
{ | |
ExpectedExceptionAttribute attribute = null; | |
object[] methodAttributes = method.GetCustomAttributes(typeof(ExpectedExceptionAttribute), true); | |
// ExpectedAttribute exists | |
if (methodAttributes.Length > 0) | |
{ | |
attribute = (ExpectedExceptionAttribute)methodAttributes[0]; | |
} | |
// ExpectedAttribute is for thrown exception | |
return attribute != null && (attribute.ExceptionName == e.GetType().Name || attribute.ExceptionType == e.GetType() || attribute.ExpectedMessage == e.Message); | |
} | |
} | |
/// <summary> | |
/// The result of a UnitTest method | |
/// </summary> | |
public class UnitTestResult | |
{ | |
/// <summary> | |
/// Initializes a new instance of the <see cref="UnitTestResult"/> class. The test run was success. | |
/// </summary> | |
/// <param name="name">The name of the method</param> | |
public UnitTestResult(string name) | |
: this(name, null) | |
{ | |
this.Success = true; | |
} | |
/// <summary> | |
/// Initializes a new instance of the <see cref="UnitTestResult"/> class. The test run was a failure. | |
/// </summary> | |
/// <param name="name">The name of the test method</param> | |
/// <param name="exception">The exception that was thrown from the test</param> | |
public UnitTestResult(string name, Exception exception) | |
{ | |
this.Name = name; | |
this.Exception = exception; | |
} | |
/// <summary> | |
/// Gets the name of the test method. | |
/// </summary> | |
/// <value>The name of the test method</value> | |
public string Name { get; private set; } | |
/// <summary> | |
/// Gets a value indicating whether this <see cref="UnitTestResult"/> is success or not. | |
/// </summary> | |
/// <value><c>true</c> if success; otherwise, <c>false</c>.</value> | |
public bool Success { get; private set; } | |
/// <summary> | |
/// Gets the exception thrown from the test method | |
/// </summary> | |
/// <value>The exception.</value> | |
public Exception Exception { get; private set; } | |
/// <summary> | |
/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>. | |
/// </summary> | |
/// <returns> | |
/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>. | |
/// </returns> | |
public override string ToString() | |
{ | |
return this.Name; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<system.web> | |
<pages> | |
<controls> | |
<add tagPrefix="litemedia" namespace="LiteMedia.Utils.Web" assembly="LiteMedia.Utils" /> | |
</controls> | |
</pages> | |
</system.web> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment