You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.8 KiB
112 lines
3.8 KiB
#nullable enable |
|
using System.Reflection; |
|
|
|
namespace Bit.Test.Common.AutoFixture.Attributes; |
|
|
|
/// <summary> |
|
/// This attribute helps to generate all possible combinations of the provided pattern values for a given number of parameters. |
|
/// <remarks> |
|
/// <para> |
|
/// The repeating pattern values should be provided as an array for each parameter. Currently supports up to 3 parameters. |
|
/// </para> |
|
/// <para> |
|
/// The attribute is a variation of the <see cref="BitAutoDataAttribute"/> attribute and can be used in the same way, except that all fixed value parameters needs to be provided as an array. |
|
/// </para> |
|
/// <para> |
|
/// Note: Use it with caution. While this attribute is useful for handling repeating parameters, having too many parameters should be avoided as it is considered a code smell in most of the cases. |
|
/// If your test requires more than 2 repeating parameters, or the test have too many conditions that change the behavior of the test, consider refactoring the test by splitting it into multiple smaller ones. |
|
/// </para> |
|
/// </remarks> |
|
/// <example> |
|
/// 1st example: |
|
/// <code> |
|
/// [RepeatingPatternBitAutoData([false], [1,2,3])] |
|
/// public void TestMethod(bool first, int second, SomeOtherData third, ...) |
|
/// </code> |
|
/// Would generate the following test cases: |
|
/// <list type="bullet"> |
|
/// <item>false, 1</item> |
|
/// <item>false, 2</item> |
|
/// <item>false, 3</item> |
|
/// </list> |
|
/// 2nd example: |
|
/// <code> |
|
/// [RepeatingPatternBitAutoData([false, true], [false, true], [false, true])] |
|
/// public void TestMethod(bool first, bool second, bool third) |
|
/// </code> |
|
/// Would generate the following test cases: |
|
/// <list type="bullet"> |
|
/// <item>false, false, false</item> |
|
/// <item>false, false, true</item> |
|
/// <item>false, true, false</item> |
|
/// <item>false, true, true</item> |
|
/// <item>true, false, false</item> |
|
/// <item>true, false, true</item> |
|
/// <item>true, true, false</item> |
|
/// <item>true, true, true</item> |
|
/// </list> |
|
/// </example> |
|
/// </summary> |
|
public class RepeatingPatternBitAutoDataAttribute : BitAutoDataAttribute |
|
{ |
|
private readonly List<object?[]> _repeatingDataList; |
|
|
|
public RepeatingPatternBitAutoDataAttribute(object?[] first) |
|
{ |
|
_repeatingDataList = AllValues([first]); |
|
} |
|
|
|
public RepeatingPatternBitAutoDataAttribute(object?[] first, object?[] second) |
|
{ |
|
_repeatingDataList = AllValues([first, second]); |
|
} |
|
|
|
public RepeatingPatternBitAutoDataAttribute(object?[] first, object?[] second, object?[] third) |
|
{ |
|
_repeatingDataList = AllValues([first, second, third]); |
|
} |
|
|
|
public override IEnumerable<object?[]> GetData(MethodInfo testMethod) |
|
{ |
|
if (_repeatingDataList.Count == 0) |
|
{ |
|
yield return base.GetData(testMethod).First(); |
|
} |
|
|
|
foreach (var repeatingData in _repeatingDataList) |
|
{ |
|
var bitData = base.GetData(testMethod).First(); |
|
for (var i = 0; i < repeatingData.Length; i++) |
|
{ |
|
bitData[i] = repeatingData[i]; |
|
} |
|
|
|
yield return bitData; |
|
} |
|
} |
|
|
|
private static List<object?[]> AllValues(object?[][] parameterToPatternValues) |
|
{ |
|
var result = new List<object?[]>(); |
|
GenerateCombinations(parameterToPatternValues, new object[parameterToPatternValues.Length], 0, result); |
|
return result; |
|
} |
|
|
|
private static void GenerateCombinations(object?[][] parameterToPatternValues, object?[] current, int index, |
|
List<object?[]> result) |
|
{ |
|
if (index == current.Length) |
|
{ |
|
result.Add((object[])current.Clone()); |
|
return; |
|
} |
|
|
|
var patternValues = parameterToPatternValues[index]; |
|
|
|
foreach (var value in patternValues) |
|
{ |
|
current[index] = value; |
|
GenerateCombinations(parameterToPatternValues, current, index + 1, result); |
|
} |
|
} |
|
}
|
|
|