forked from microsoft/testfx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added TestDataSource and DynamicData attributes (microsoft#195)
* Dynamic Data attribute implementation. * Added E2E tests. * Added more tests. * PR feedback. * Added sealed for DynamicDataAttribute. * Changed TestDataSource to ITestDataSource. * Fixed failing tests.
- Loading branch information
1 parent
bf5fb4f
commit 50c26d1
Showing
35 changed files
with
891 additions
and
61 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
143 changes: 143 additions & 0 deletions
143
src/TestFramework/MSTest.Core/Attributes/DynamicDataAttribute.cs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 1,143 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace Microsoft.VisualStudio.TestTools.UnitTesting.Attributes | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Reflection; | ||
|
||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
|
||
/// <summary> | ||
/// Enum to specify whether the data is stored as property or in method. | ||
/// </summary> | ||
public enum DynamicDataSourceType | ||
{ | ||
/// <summary> | ||
/// Data is declared as property. | ||
/// </summary> | ||
Property = 0, | ||
|
||
/// <summary> | ||
/// Data is declared in method. | ||
/// </summary> | ||
Method = 1 | ||
} | ||
|
||
/// <summary> | ||
/// Attribute to define dynamic data for a test method. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] | ||
public sealed class DynamicDataAttribute : Attribute, ITestDataSource | ||
{ | ||
private string dynamicDataSourceName; | ||
|
||
private Type dynamicDataDeclaringType; | ||
|
||
private DynamicDataSourceType dynamicDataSourceType; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="DynamicDataAttribute"/> class. | ||
/// </summary> | ||
/// <param name="dynamicDataSourceName"> | ||
/// The name of method or property having test data. | ||
/// </param> | ||
/// <param name="dynamicDataSourceType"> | ||
/// Specifies whether the data is stored as property or in method. | ||
/// </param> | ||
public DynamicDataAttribute(string dynamicDataSourceName, DynamicDataSourceType dynamicDataSourceType = DynamicDataSourceType.Property) | ||
{ | ||
this.dynamicDataSourceName = dynamicDataSourceName; | ||
this.dynamicDataSourceType = dynamicDataSourceType; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="DynamicDataAttribute"/> class. | ||
/// </summary> | ||
/// <param name="dynamicDataSourceName"> | ||
/// The type in which the test data is declared (as property or in method). | ||
/// </param> | ||
/// <param name="dynamicDataDeclaringType"> | ||
/// The declaring type of property or method having data. | ||
/// </param> | ||
/// <param name="dynamicDataSourceType"> | ||
/// Specifies whether the data is stored as property or in method. | ||
/// </param> | ||
public DynamicDataAttribute(string dynamicDataSourceName, Type dynamicDataDeclaringType, DynamicDataSourceType dynamicDataSourceType = DynamicDataSourceType.Property) | ||
: this(dynamicDataSourceName, dynamicDataSourceType) | ||
{ | ||
this.dynamicDataDeclaringType = dynamicDataDeclaringType; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IEnumerable<object[]> GetData(MethodInfo methodInfo) | ||
{ | ||
// Check if the declaring type of test data is passed in constructor. If not, default to test method's class type. | ||
if (this.dynamicDataDeclaringType == null) | ||
{ | ||
this.dynamicDataDeclaringType = methodInfo.DeclaringType; | ||
} | ||
|
||
object obj = null; | ||
|
||
switch (this.dynamicDataSourceType) | ||
{ | ||
case DynamicDataSourceType.Property: | ||
var property = this.dynamicDataDeclaringType.GetTypeInfo().GetDeclaredProperty(this.dynamicDataSourceName); | ||
if (property == null) | ||
{ | ||
throw new ArgumentNullException(string.Format("{0} {1}", DynamicDataSourceType.Property, this.dynamicDataSourceName)); | ||
} | ||
|
||
obj = property.GetValue(null, null); | ||
|
||
break; | ||
|
||
case DynamicDataSourceType.Method: | ||
var method = this.dynamicDataDeclaringType.GetTypeInfo().GetDeclaredMethod(this.dynamicDataSourceName); | ||
if (method == null) | ||
{ | ||
throw new ArgumentNullException(string.Format("{0} {1}", DynamicDataSourceType.Method, this.dynamicDataSourceName)); | ||
} | ||
|
||
obj = method.Invoke(null, null); | ||
|
||
break; | ||
} | ||
|
||
if (obj == null) | ||
{ | ||
throw new ArgumentNullException( | ||
string.Format( | ||
FrameworkMessages.DynamicDataValueNull, | ||
this.dynamicDataSourceName, | ||
this.dynamicDataDeclaringType.FullName)); | ||
} | ||
|
||
IEnumerable<object[]> enumerable = obj as IEnumerable<object[]>; | ||
if (enumerable == null) | ||
{ | ||
throw new ArgumentNullException( | ||
string.Format( | ||
FrameworkMessages.DynamicDataIEnumerableNull, | ||
this.dynamicDataSourceName, | ||
this.dynamicDataDeclaringType.FullName)); | ||
} | ||
|
||
return enumerable; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public string GetDisplayName(MethodInfo methodInfo, object[] data) | ||
{ | ||
if (data != null) | ||
{ | ||
return string.Format(CultureInfo.CurrentCulture, FrameworkMessages.DataDrivenResultDisplayName, methodInfo.Name, string.Join(",", data)); | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
} |
This file contains 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
41 changes: 41 additions & 0 deletions
41
src/TestFramework/MSTest.Core/Interfaces/ITestDataSource.cs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 1,41 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace Microsoft.VisualStudio.TestTools.UnitTesting | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Reflection; | ||
|
||
/// <summary> | ||
/// Test data source for data driven tests. | ||
/// </summary> | ||
public interface ITestDataSource | ||
{ | ||
/// <summary> | ||
/// Gets the test data from custom test data source. | ||
/// </summary> | ||
/// <param name="methodInfo"> | ||
/// The method info of test method. | ||
/// </param> | ||
/// <returns> | ||
/// Test data for calling test method. | ||
/// </returns> | ||
IEnumerable<object[]> GetData(MethodInfo methodInfo); | ||
|
||
/// <summary> | ||
/// Gets the display name corresponding to test data row for displaying in TestResults. | ||
/// </summary> | ||
/// <param name="methodInfo"> | ||
/// The method Info of test method. | ||
/// </param> | ||
/// <param name="data"> | ||
/// The test data which is passed to test method. | ||
/// </param> | ||
/// <returns> | ||
/// The <see cref="string"/>. | ||
/// </returns> | ||
string GetDisplayName(MethodInfo methodInfo, object[] data); | ||
} | ||
} |
This file contains 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
20 changes: 19 additions & 1 deletion
20
src/TestFramework/MSTest.Core/Resources/FrameworkMessages.Designer.cs
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.