Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing interraction between two devices (via Espresso)

I'm working on P2P chat application (for Android) right now. And I would like to add some UI tests to not go through all use-cases (sending/receiving messages, connection requests, disconnections, losing connection and so on) manually every time after I change some big part of my code.

So, my initial thought was creating two sets of Espresso test for two devices, one will send requests and messages and another will be a receiver and run them simultaneously. It's just abstract idea and my question is: is that possible to run two sets of tests which will interact with each other? And even if the answer is "yes", should I implement this approach, or should I somehow mock connection mechanism and run tests only on one device? (In case this approach is fine, how can I implement that?) Can you suggest a right/better approach?

I didn't find any similar question, and I think maybe it is stupid and an answer is obvious for everybody who has much experience with testing. Anyway, the answer may be useful for some other guys in the similar situation.

Thanks in advance.

like image 702
Vasyl Glodan Avatar asked Oct 21 '25 05:10

Vasyl Glodan


1 Answers

Ok, here we are, 8 months after I asked this question and zero activity, I have even earned 'Tumbleweed' achievement.

I wouldn't say I have solved my problem with testing communication between two devices but at least I have implemented something that works, and I want to share it with anyone who may need it.

Autoresponder

Looks like there is no an easy way to run two different test on two devices simultaneously which will communicate with each other. So, I've decided to implement Autoresponder which works by a script. Basically, test sends a text message for example "respond_me" and autoresponder catches it and responds via another text for example "response" and test checks if the message was received.

Sample is simplified

I created 'CommunicationProxy' interface

interface CommunicationProxy {
    fun onMessageReceived(message: ChatMessage)
    fun onMessageSent(message: ChatMessage)
} 

and invoke its methods in a class where I receive messaging events.

private var proxy: CommunicationProxy? = ...

override fun onMessageReceived(message: ChatMessage) {
    proxy?.onMessageReceived(message)
    messageListener?.onMessageReceived(message)
}

override fun onMessageSent(message: ChatMessage) {
    proxy?.onMessageSent(message)
    messageListener?.onMessageSent(message)
}

For debug and release build types this proxy is an empty interface implementation:

class EmptyProxy : CommunicationProxy {
    override fun onMessageReceived(message: ChatMessage) {
    }
    override fun onMessageSent(message: ChatMessage) {
    }
}

I added one more build type autoresponder and instantiate CommunicationProxy implementation with some logic:

proxy = if (BuildConfig.AUTORESPONDER) AutoresponderProxy(service) else EmptyProxy()

AutoresponderProxy:

class AutoresponderProxy(private val service: ConnectionService?) : CommunicationProxy {

    companion object {

        const val COMMAND_SEND_TEXT = "-send_text"

        const val RESPONSE_RECEIVED = "+text_message"
    }

    override fun onMessageReceived(message: ChatMessage) {

        service?.let {

            when {
                message.text == COMMAND_SEND_TEXT -> {
                    it.sendMessage(RESPONSE_RECEIVED)
                }

                ...
            }
        }
    }

    override fun onMessageSent(message: ChatMessage) {
    }
}

I install autoresponder on one device and another one runs Espresso test which types '-send_text' text into EditText and presses 'Send' button, and waits when '+text_message' text appears in RecyclerView.

Idling resources?

This sample is extremely simplified, and my CommunicationProxy interface has 25 methods, I tried to integrate IdlingResources but I couldn't manage all those callbacks. I use Thread.sleep(...) to wait for a response.

Flakiness

My test runs fine but I understand how flaky it may be, anyway I implemented this approach to simplify my life and don't do regression testing every time manually, I don't plan to run it on CI or something like this.

like image 110
Vasyl Glodan Avatar answered Oct 22 '25 19:10

Vasyl Glodan