[Channels] How to write tests with database access?

瀏覽次數:81 次
跳到第一則未讀訊息

Neraste

未讀,
2018年7月19日 上午11:19:042018/7/19
收件者:django...@googlegroups.com

Hello Django users,

This sounds like a pretty newbish question, but I am struggling on how to write tests for Django-channels 2 websocket consumers that access the database. I am not familiar with pytest and asynchronous programming (the bread and butter of Channels testing), so while I caught up with pytest, I am still a bit lost between `async` and `await`.

Using Django/Django-REST, when I test a view method which modifies a database object for a given request, here is what I usually do:

  1. Assert the initial state of the object ;
  2. Use the test client to send the request ;
  3. Assert the outcome of the request ;
  4. Assert the final state of the object, which should be different.

All of this synchronously. With Channels, I thought I could do the same for a consumer method which modifies a database object on a given event:

  1. Assert the initial state of the object ;
  2. Use the test communicator to send the event ;
  3. Assert the final state of the object, which should have changed.

All of this asynchronously, as stated in the documentation, but this is a synchronous test scenario! Obviously, it does not work, as step 2. is executed with `await` and step 3. is achieved before step 2. finishes. I tried to execute step 2. synchronously using `async_to_sync` but it does not work (I can give details).

I am missing something, how can I test such a consumer method? Is this possible? The documentation does not give any hint on this…

Help would be much appreciated!

Cheers,

-- 
Neraste

Andrew Godwin

未讀,
2018年7月22日 中午12:44:522018/7/22
收件者:django...@googlegroups.com
Asynchronous testing is very hard, unfortunately. I suspect what you are doing is awaiting the sending of the message, but not awaiting any response back, so your test continues once it's sent the message into the application but not waiting for that application to finish processing.

The best pattern for this is probably to send something back when you've finished processing and await receiving that, then you should guarantee that the work has been finished before your test continues.

Andrew

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/c22c1afb-ff85-5af9-66f6-a94cdc77a545%40gmail.com.
For more options, visit https://groups.google.com/d/optout.

Neraste

未讀,
2018年7月28日 上午10:49:392018/7/28
收件者:Django users
Thanks for the hint, Andrew. I think it is a neat approach. But I start to wonder if asynchronous tests + database manipulation are naturally and painlessly compatible.

Bill Torcaso

未讀,
2018年7月30日 上午9:38:292018/7/30
收件者:Django users
The question is whether testing asynchronous operations and <any other stateful information> is compatible.

In my understanding, Andrew's hint points you in the only good direction.  You've got to turn the async initiate/complete cycle back into a synchronous flow.

You can poll from another thread, or use a message queue, or any of a number of approaches.  But there is no way around the need to wait until completion before your test the state after completion.
回覆所有人
回覆作者
轉寄
0 則新訊息