-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRepeatForTime.cs
More file actions
92 lines (84 loc) · 4.04 KB
/
RepeatForTime.cs
File metadata and controls
92 lines (84 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using System;
using System.Diagnostics;
using Gallio.Common.Reflection;
using Gallio.Framework;
using Gallio.Framework.Pattern;
using Gallio.Model;
using MbUnit.Framework;
namespace ProtoTest.Nightshade
{
namespace Tests.Common
{
/// <summary>
/// Repeats a test until the time has passed
/// </summary>
[AttributeUsage(PatternAttributeTargets.Test, AllowMultiple = true, Inherited = true)]
public class RepeatForTimeAttribute : TestDecoratorPatternAttribute
{
private readonly int _minutes;
/// <summary>
/// Will re-run the test method each time we get a failure for a limited number of attempts.
/// </summary>
/// <example>
/// <code><![CDATA[
/// [Test]
/// [RepeatOnFailure(3)]
/// public void Test()
/// {
/// // This test will be executed until we get a pass or have run it 3 times.
/// // Eg, if the first test run fails, we will run it again, and if the second attempt passes, then we will stop.
/// // if 3 attempts all fail, we dont try anymore
/// }
/// ]]></code>
/// </example>
/// <param name="maxNumberOfAttempts">The number of times to repeat the test while searching for a pass</param>
/// <exception cref="ArgumentOutOfRangeException">
/// Thrown if <paramref name="maxNumberOfAttempts" />
/// is less than 1.
/// </exception>
public RepeatForTimeAttribute(int minutes)
{
if (minutes < 1)
throw new ArgumentOutOfRangeException("minutes",
@"The minutes must be at least 1.");
_minutes = minutes;
}
/// <inheritdoc />
protected override void DecorateTest(IPatternScope scope, ICodeElementInfo codeElement)
{
scope.TestBuilder.TestInstanceActions.RunTestInstanceBodyChain.Around(
delegate(PatternTestInstanceState state,
Gallio.Common.Func<PatternTestInstanceState, TestOutcome> inner)
{
TestOutcome outcome = TestOutcome.Passed;
//int failureCount = 0;
// we will try up to 'max' times to get a pass, if we do, then break out and don't run the test anymore
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for(int i=0;stopwatch.Elapsed < TimeSpan.FromMinutes(_minutes);i++)
{
string name = String.Format("Repetition #{0}", i + 1);
DiagnosticLog.WriteLine(name);
TestContext context = TestStep.RunStep(name, delegate
{
TestOutcome innerOutcome = inner(state);
//if we get a fail, and we have used up the number of attempts allowed to get a pass, throw an error
if (innerOutcome.Status != TestStatus.Passed)
{
throw new SilentTestException(innerOutcome);
}
}, null, false, codeElement);
outcome = context.Outcome;
// escape the loop if the test has passed, otherwise increment the failure count
//if (context.Outcome.Status == TestStatus.Passed)
// break;
// failureCount++;
}
Log.Message(String.Format("Ran the test for {0} minutes", _minutes));
//TestLog.WriteLine(String.Format("Ran the test for {0} minutes", _minutes));
return outcome;
});
}
}
}
}