我如何使用线程执行单元测试?

5 浏览
0 Comments

我如何使用线程执行单元测试?

这个问题已经在这里有答案了

如何对多线程代码进行单元测试?

行政摘要: 当线程中抛出断言错误时,单元测试不会死亡。这是有道理的,因为一个线程不应该允许崩溃另一个线程。问题是如何做到以下两点之一:1)当辅助线程的第一个崩溃时使整个测试失败,或2)在所有完成后循环遍历并确定每个线程的状态(请参见下面的代码)。后者的一种方法是有一个每个线程状态变量,例如“布尔[]状态”并且具有“statuses[i] == false”的含义是线程失败(这可以扩展以捕获更多信息)。然而,这不是我想要的:当断言错误被抛出时,我希望它像任何其他单元测试一样失败。这可能吗?是否值得称赞?

我感到无聊,于是决定在我的单位测试中生成一堆线程,然后让它们调用服务方法,就为了好玩。代码大致如下:

Thread[] threads = new Thread[MAX_THREADS];
for( int i = 0; i < threads.length; i++ ) { threads[i] = new Thread( new Runnable() { private final int ID = threadIdSequenceNumber++; public void run() { try { resultRefs[ID] = runTest( Integer.toString( ID ) ); // returns an object } catch( Throwable t ) { // this code is EVIL - it catches even // Errors - don't copy it - more on this below final String message = "error testing thread with id => "
                            + ID;
                logger.debug( message, t );
                throw new IllegalStateException( message, t ); 
                // need to wrap throwable in a 
                // run time exception so it will compile
            }
        }
    } );
}

在这之后,我们将循环遍历线程数组并启动每个线程。然后我们等待它们全部完成。最后,我们将对结果引用进行一些检查。

for( Thread thread : threads )
    thread.start();
logger.debug( "waiting for threads to finish ..." );
boolean done = false;
while( !done ) {
    done = true;
    for( Thread thread : threads )
        if( thread.isAlive() )
            done = false;
}
for( int i = 0; i < resultRefs.length; i++ ) {
    assertTrue( "you've got the world messed, dawg!",
            myCondition(resultRefs[i]) );

这里的问题是什么?你是否注意到那个讨厌的try-catch-throwable块?我只是添加了一个临时hack,以便我可以看到发生了什么。在runTest(String)中做了一些断言,例如assertNotNull(null),但由于它在不同的线程中,它不会导致单元测试失败!

我的猜测是我们需要以某种方式迭代遍历线程数组,检查每个线程的状态,并在线程以不良方式终止时手动导致断言错误。那么提供这些信息(死亡线程的堆栈跟踪)的方法叫什么?

admin 更改状态以发布 2023年5月22日
0
0 Comments

Google测试博客刊登了一篇有关这个主题的精彩文章,非常值得阅读:http://googletesting.blogspot.com/2008/08/tott-sleeping-synchronization.html

它是用Python编写的,但我认为其中的原则可以直接转移到Java中。

0
0 Comments

并发是那些非常难以进行单元测试的事情之一。如果你想要测试每个线程内的代码是否按照预期运行,也许你应该单独测试这段代码而不是将其放在上下文中进行测试。
如果在这个例子中线程协同以达成某个结果,也许你可以在不使用线程的情况下测试这种协同。这可以通过按顺序执行所有参与协同的部分来完成。
如果你想要测试竞态条件和这种情况下的问题,单元测试并不是最好的方法。你可能会得到有时成功、有时失败的测试结果。
总之,我认为你的问题可能是你进行了太高层级的单元测试。
希望这可以帮到你。

0