2016-03-25 4 views
0

У меня есть клиентский и серверный модуль, каждый из которых может быть запущен функцией. Мне просто нужно найти способ запустить стенд параллельно, которые:Как использовать потоки для функциональных тестов приложения клиентского сервера?

  1. в случае исключения в клиент/сервер остановится другой, так что тест бегун бы не остаться застрял

  2. в случае за исключения в архитектуре клиент/сервер будет печатать исключение или распространить его на бегуна, чтобы я мог видеть это и отладки клиент/сервер с помощью тестового набора

  3. бы предпочтительно использовать темы для повышения производительности

Первое предварительный с простыми нитями закончились уродливой os._exit(1) при ловле исключения в методе выполнения резьбы (который убивает тест бегун ...) Edit: с заправочным пакетом

Вторыми предварительным (до старайтесь избегать os._exit()) с concurrent.futures.ThreadPoolExecutor. Это позволяет исключить исключение из потока, но я все еще не могу найти способ прервать другой поток.

with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor: 
    server_future = executor.submit(server) 
    client_future = executor.submit(client) 

    concurrent.futures.wait([server_future, client_future], 
          return_when=concurrent.futures.FIRST_EXCEPTION) 

    if client_future.done() && client_future.exception(): 
     # we can handle the client exception here 
     # but how to stop the server from waiting the client? 
     # also, raise is blocking 

    if server_future.done() && server_future.exception(): 
     # same here 
  • Есть ли способ для достижения этой цели с потоками?
  • Если нет в потоках, есть ли простой способ протестировать приложение клиентского сервера? (Я думаю, что двух первых требований достаточно, чтобы иметь пригодное для использования решение)

Редактировать: клиент или сервер будут заблокированы при вызове accept() или receive(), поэтому я не могу периодически путать flag a решите выйти. (один из классических способов остановить поток)

ответ

1

Вы можете использовать пакет threading. Имейте в виду, что эта сила, убивающая нить, не очень хорошая идея, as discussed here. Кажется, нет официального способа убить Thread в Python, но вы можете следовать одному из примеров, приведенных в связанном сообщении.

Теперь вам нужно подождать, пока один поток выйдет, прежде чем останавливать другой, избегая застревания вашего тестового бегуна. Вы можете использовать Threads, обертывающий ваш запуск сервера/клиента, и ваш основной поток ожидает, когда либо клиент/сервер Thread выйдет, прежде чем убить другого.

Вы можете определить свой клиент/сервер тему так:

# Server thread (replace 
class testServerThread (threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 
     # Do stuff if required 

    def run(self): 
     try: 
      startServer() # Or startClient() for your client thread 
     except: Exception 
      # Print your exception here, so you can debug 

Затем запустите оба клиента и сервера нитку, и ждать, пока один из них, чтобы выйти. Как только один из них больше не жив, вы можете убить другого и продолжить тестирование.

# Create and start client/server 
serverThread = testServerThread() 
clientThread = testClientThread() 

serverThread.start() 
clientThread.start() 

# Wait at most 5 seconds for them to exit, and loop if they're still both alive 
while(serverThread.is_alive() and clientThread.is_alive()): 
    serverThread.join(5) 
    clientThread.join(5) 

# Either client or server exited. Kill the other one. 
# Note: the kill function you'll have to define yourself, as said above 
if(serverThread.is_alive()): 
    serverThread.kill() 

if(clientThread.islive()): 
    clientThread.kill() 

# Done! Your Test runner can continue its work 

Центральная часть кода является join() функция:

Подождите, пока поток не прекращается. Это блокирует вызывающий поток до тех пор, пока поток, метод join() не будет завершен - как обычно, так и через необработанное исключение - или до тех пор, пока не произойдет дополнительный тайм-аут.

Таким образом, в нашем случае он будет ждать 5 секунд для клиента и 5 секунд для сервера, и если оба из них все еще живы после этого, он снова запустится. Всякий раз, когда один из них выходит, цикл останавливается, и оставшаяся нить будет убита.

+0

Первая попытка была с пакетом с резьбой, я должен был упомянуть об этом. Я искал, как убить поток, но не смог применить решение, потому что я не контролировал то, что делает нити (не может периодически проверять флаг). В моем случае они блокировали бы выполнение accept() или receive() в сокете. Но после того, как я выяснил, как прервать эти операции, я узнал, что могу просто закрыть() сокет! Большое спасибо за косвенное руководство меня к этому решению! – tuxayo