如何使用线程执行单元测试? [英] How do I perform a Unit Test using threads?

查看:102
本文介绍了如何使用线程执行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

执行摘要:在线程中引发断言错误时,单元测试不会消失.这是有道理的,因为不应允许一个线程使另一个线程崩溃.问题是我该如何1)当第一个辅助线程崩溃时使整个测试失败,或者2)遍历并确定每个线程完成后的状态(请参见下面的代码).进行后者的一种方法是通过每个线程具有状态变量,例如,"boolean [] statuss"和具有"statuses [i] == false"的意思是线程失败(可以扩展以捕获更多信息).但是,这不是我想要的:抛出断言错误时,我希望它像其他任何单元测试一样失败.这有可能吗?是可取的吗?

Executive Summary: When assertion errors are thrown in the threads, the unit test doesn't die. This makes sense, since one thread shouldn't be allowed to crash another thread. The question is how do I either 1) make the whole test fail when the first of the helper threads crashes or 2) loop through and determine the state of each thread after they have all completed (see code below). One way of doing the latter is by having a per thread status variable, e.g., "boolean[] statuses" and have "statuses[i] == false" mean that the thread failed (this could be extended to capture more information). However, that is not what I want: I want it to fail just like any other unit test when the assertion errors are thrown. Is this even possible? Is it desirable?

我很无聊,所以我决定在单元测试中生成一堆线程,然后让它们调用服务方法(仅出于此目的).该代码大致类似于:

I got bored and I decided to spawn a bunch of threads in my unit test and then have them call a service method, just for the heck of it. The code looks approximately like:

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
            }
        }
    } );
}

此后,我们将遍历线程数组并开始每个线程.之后,我们将等待它们全部完成.最后,我们将对结果引用进行一些检查.

After this, we will loop through the array of threads and start each one. After that we will wait for them all to finish. Finally, we will perform some checks on the result references.

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),但是由于它位于不同的线程中,因此不会导致单元测试失败!!!

Here's the problem. Did you notice that nasty try-catch-throwable block? I just added that as a temporary hack so I could see what was going on. In runTest( String ) a few assertions are made, e.g., assertNotNull( null ), but since it is in a different thread, it doesn't cause the unit test to fail!!!!

我的猜测是,如果线程以令人讨厌的方式终止,我们将需要以某种方式遍历线程数组,检查每个线程的状态,并手动导致断言错误.提供此信息(死线程的堆栈跟踪)的方法的名称是什么.

My guess is that we will need to somehow iterate over the threads array, check the status of each, and manually cause an assertion error if the thread terminated in a nasty way. What's the name of the method that gives this information (the stack trace of the dead thread).

推荐答案

并发是很难进行单元测试的事情之一.如果您只是想测试每个线程中的代码是否正在执行应该测试的内容,也许您应该只测试与上下文隔离的代码. 如果在此示例中,线程进行协作以达到结果,则可以在不使用线程的情况下测试该协作.这可以通过顺序执行所有协作部分来完成. 如果要测试比赛条件和此类情况,则单元测试不是最好的方法.您将获得有时会失败有时又不会失败的测试. 总而言之,我认为您的问题可能是您的单元测试水平过高. 希望这会有所帮助

Concurrency is one of those things that are very difficult to unit test. If you are just trying to test that the code inside each thread is doing what it is supposed to test, may be you should just test this code isolated of the context. If in this example the threads collaborate to reach a result, may be you can test that collaboration without using threads. That would be done by executing all the collaborative parts sequentially. If you want to test for race conditions and these kind of things, unit testing is not the best way. You will get tests that sometimes fail and sometimes don´t fail. To summarize, I think that may be your problem is that you are unit testing in a level too high. Hope this helps

这篇关于如何使用线程执行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆