我目前正在尝试实施StopWatch
课程。界面类似于:
interface IStopWatch {
void Run();
void Stop();
int SecondsElapsed { get; }
int MinutesElapsed { get; }
}
基本上我的应用程序需要使用StopWatch
,但出于测试目的,有一种人工修改StopWatch
es'结果的方式很好,所以这就是我的原因使我的所有代码都引用IStopWatch
而不是.NET的System.Stopwatch
。
当我正在尝试开发这个Test-First时,我必须在编写测试后才为我的StopWatch
类创建代码。我已经意识到我要做的测试不会是单元测试,因为我在内部使用.NET的System.Stopwatch
类。
所以,在我的承诺中,我现在唯一能做的就是测试如下:
[TestMethod]
public void Right_After_Calling_Run_Elapsed_Minutes_Equals_Zero() {
IStopWatch stopWatch = new StopWatch();
stopWatch.Run();
Assert.AreEqual<int>(0, stopWatch.ElapsedMinutes);
}
[TestMethod]
public void One_Second_After_Run_Elapsed_Seconds_Equals_One() {
IStopWatch stopWatch = new StopWatch();
stopWatch.Run();
Thread.Sleep(1000 + 10);
Assert.AreEqual<int>(1, stopWatch.ElapsedSeconds);
}
[TestMethod]
public void Sixty_Seconds_After_Run_Elapsed_Minutes_Equals_One() {
IStopWatch stopWatch = new StopWatch();
stopWatch.Run();
Thread.Sleep(60 * 1000 + 1000);
Assert.AreEqual<int>(1, stopWatch.ElapsedMinutes);
}
我知道我不能像我的单元测试那样频繁地运行它,但我认为我无能为力。我的方法是正确的还是我错过了什么?
由于
所以我最终遵循了Quinn351和Sjoerd的建议,编写了一些使用DateTimes而不是.NET的Stopwatch类的东西:
public class MyStopWatch : IMyStopWatch {
private DateTime? firstDateTime = null;
private DateTime? secondDateTime = null;
private bool isRunning = false;
public void Start() {
isRunning = true;
firstDateTime = DateTime.Now;
}
public void Stop() {
isRunning = false;
secondDateTime = DateTime.Now;
}
public void Reset() {
firstDateTime = null;
secondDateTime = null;
isRunning = false;
}
public TimeSpan GetTimeElapsed() {
return secondDateTime.Value.Subtract(firstDateTime.Value);
}
}
这允许我进行其他两个日期都有getter / setter的实现,这样我就可以让GetTimeElapsed()返回我想要的任何内容。
答案 0 :(得分:3)
为什么“人为地修改StopWatches”结果“?!如果您要修改结果,测试的全部目的是什么?
至于测试,你还应该测试停止方法,你应该测试秒数是否大约是分钟数的60倍。
您正在编写的类也可以在内部使用StopWatch,然后根据请求修改结果(然后您可以始终返回到原始结果)。
PS:方法名称应该更短,没有下划线。
答案 1 :(得分:2)
你的秒表类可能从某个地方获取日期和时间。创建一个返回当前日期的对象。这将是一个非常简单的课程。测试时,传入一个模拟对象,返回一个假的日期和时间。通过这种方式,您可以在测试中假装已经过了很多秒。
class DateTime {
public Date getDate() {
return System.DateTime.Now();
}
}
class MockDateTime {
public Date getDate() {
return this.fakeDate;
}
}
class StopwatchTest {
public void GoneInSixtySeconds() {
MockDateTime d = new MockDateTime();
d.fakeDate = '2010-01-01 12:00:00';
Stopwatch s = new Stopwatch();
s.Run();
d.fakeDate = '2010-01-01 12:01:00';
s.Stop();
assertEquals(60, s.ElapsedSeconds);
}
}
答案 2 :(得分:1)
一个问题是秒表在具有可变时钟速度的处理器上是不准确的,即大多数当前的处理器,如下面的讨论所示
C# Stopwatch shows incorrect time
因此使用Thread.Sleep不会给你准确的时间。您最好使用DateTime.Now
实现自己的秒表版本答案 3 :(得分:0)
除了上面的编辑之外:不要使用这种方法来确定经过的时间!它在以下情况下效果不佳:
......可能还有很多其他条件。