如何测试计时器?

cca*_*ers 11 java junit timer

我想为一个方法编写测试,该方法在特定的intervall中调用观察者,以便他们执行一个方法.timer-object在自己的线程中运行.

要测试的计时器的方法
private long waitTime;

public Metronome(int bpm) {
    this.bpm = bpm;
    this.waitTime = calculateWaitTime();
    this.running = false;
}

public void run() {
    long startTime = 0, estimatedTime = 0, threadSleepTime = 0;

    running = true;

    while (running) {
        startTime = System.nanoTime();

        tick();// notify observers here

        estimatedTime = System.nanoTime() - startTime;
        threadSleepTime = waitTime -estimatedTime;
        threadSleepTime = threadSleepTime < 0 ? 0 : threadSleepTime;

        try {
            Thread.sleep(threadSleepTime / 1000000l);

        } catch (InterruptedException e) {
                // sth went wrong
        }
    }
}
Run Code Online (Sandbox Code Playgroud) 来自我的测试类的片段
private int ticks;
private long startTime;
private long stopTime;

@Test
public void tickTest(){
    metronome.setBpm(600);
    startTime = System.nanoTime();
    metronome.run();
    long duration = stopTime - startTime;
    long lowThreshold  =  800000000;
    long highThreshold =  900000000;
    System.out.println(duration);
    assertTrue(lowThreshold < duration); 
    assertTrue(duration <= highThreshold);      
}

@Override
public void update(Observable o, Object arg) {
    ticks ++;       
    if(ticks == 10){
        metronome.stop();
        stopTime = System.nanoTime();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我的testclass注册为相关对象的观察者,这样我就可以计算tick()执行的次数.测试测量执行前后的时间,但是对我来说,以这种方式测试行为感觉很尴尬.

有任何改进测试的建议吗?

cca*_*ers 2

根据你的评论我改变了我的代码。我现在创建了一个私有类,它实现了在我的计时器上注册的接口,而不是在我的测试类中实现观察者接口。

感谢您的时间和想法。

代码现在如下所示:

修改后的测试代码
@Test(timeout = 2000)
public void tickTest(){     
    long lowThreshold  = 400000000;
    long highThreshold = 600000000;

    TickCounter counter = new TickCounter();
    metronome.addObserver(counter);
    metronome.setBpm(600);

    startTime = System.nanoTime();
    metronome.run();
    long duration = System.nanoTime() - startTime;


    assertTrue(lowThreshold <= duration);
    assertTrue(duration <= highThreshold);      
}

private class TickCounter implements Observer{
    private int ticks;

    public TickCounter(){
        ticks = 0;
    }

    @Override
    public void update(Observable o, Object arg) {
        ticks++;        
        if(ticks == 5){
            metronome.stop();
        }
    }       
}
Run Code Online (Sandbox Code Playgroud) 我修改后的计时器的片段
private long expectedTime; // calculated when bpm of timer is set

@Override
public void run() {
    long startTime = 0, elapsedTime = 0, threadSleepTime = 0;

    running = true;

    while (running) {
        startTime = System.nanoTime();

        tick();

        elapsedTime     = System.nanoTime() - startTime;

        threadSleepTime = expectedTime - elapsedTime;
        threadSleepTime = threadSleepTime < 0 ? 0 : threadSleepTime;

        try { TimeUnit.NANOSECONDS.sleep(threadSleepTime); } catch (Exception e) { }
    }
}
Run Code Online (Sandbox Code Playgroud)

我最大的问题可能是,我在 JUnit 测试用例中实现了观察者界面。所以我创建了一个私人观察者,专门计算tick执行的次数。然后计数器停止我的计时器。

测试方法测量时间并断言所需的时间在我定义的限制之间。