我如何使用线程执行单元测试?
我如何使用线程执行单元测试?
这个问题已经在这里有答案了:
行政摘要: 当线程中抛出断言错误时,单元测试不会死亡。这是有道理的,因为一个线程不应该允许崩溃另一个线程。问题是如何做到以下两点之一: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日
Google测试博客刊登了一篇有关这个主题的精彩文章,非常值得阅读:http://googletesting.blogspot.com/2008/08/tott-sleeping-synchronization.html
它是用Python编写的,但我认为其中的原则可以直接转移到Java中。