Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kasperskylab/adbserver

Adb Server for Espresso tests
https://github.com/kasperskylab/adbserver

adb espresso kaspresso ui-tests

Last synced: about 1 month ago
JSON representation

Adb Server for Espresso tests

Awesome Lists containing this project

README

        

[![CircleCI](https://circleci.com/gh/KasperskyLab/AdbServer.svg?style=svg)](https://circleci.com/gh/KasperskyLab/AdbServer)

# [DEPRECATED] Autotests Adb Server

Please, use [Kaspresso](https://github.com/KasperskyLab/Kaspresso) where AdbServer was migrated.

Detailed information is available [here](https://github.com/KasperskyLab/Kaspresso/blob/master/wiki/06_AdbServer.md).

## What is it?
When you are writing ui-tests you need do some actions with device sometimes.
You may to execute a big part of those actions by [ADB](https://developer.android.com/studio/command-line/adb).
But Espresso doesn't contain a mechanism allowing Adb commands fulfilling although Appium does.

Why? In Espresso your app and tests are in device. In Appium your tests are in Desktop or Server.
So in Espresso you can't call adb because you can't call adb from inside the device.

That's why we have created **Autotests Adb Server** to compensate for the Espresso disadvantage.



The main idea of the tool is so similar with idea of Appium.
We need an ability to include in our tests some external thing from where we would send adb-commands to a device.
This external thing can be Desktop or Server.

That's why the tool is consist of two parts: **Desktop** and **Device**.

**Desktop** - is the server listening commands from devices to execute adb-commands.

**Device** - is the client sending commands to the server from your tests.

## Usage

#### Server/Desktop
You need to start the **Desktop** on your host (desktop/server) **before** tests' start to execute.

To start the **Desktop** please copy built library from */artifacts/desktop.jar* to convenient for you place.

The next is to execute a simple command in your host's cmd:
```
java -jar desktop.jar
```
Also, you can set additional options as it's shown in the example below:
```
java -jar desktop.jar emulators=emulator-5554,emulator-5556 adbServerPort=5041
```
where:

emulators - you set a list of emulators that can be captured by desktop.jar

adbServerPort - you set the adb server port number (the default value is 5037)

#### Device
1) [Add `adbserver-device` dependency in your project](https://github.com/KasperskyLab/AdbServer#integration)
2) Give permissions for an access to the Internet
```gradle

```
3) Use the class:
```kotlin
object AdbTerminal {

fun connect() { }

fun disconnect() { }

/**
* Please first of all call [connect] method to establish a connection
*/
fun executeAdb(command: String): CommandResult { }

/**
* Please first of all call [connect] method to establish a connection
*/
fun executeCmd(command: String): CommandResult { }

}
```
As you are seeing you need to establish connection by ```connect``` method calling before to execute adb or simple cmd command.

For a reminder: adb-command is also cmd command but it starts with ```adb``` key word.

After the session please close the connection by ```disconnect``` method.

```executeAdb``` and ```executeCmd``` are synchronous methods to not reorder a line of commands because if commands were completed in incorrect order it may to lead inconsistent state of the app and the device.

Also these methods don't throw any exception. All possible results are mapping into ```CommandResult```.

All methods of ```AdbTerminal``` may be call from any thread.

So, please observe **example** module.

### Logs
Let's consider what the developer looks in the logs on the host and the device.

#### The host logs
*desktop.jar* is running and waiting devices. But no one device exists in the current environment.
```
INFO:_____tag=MAIN______________________________________message => arguments: emulators=[], adbServerPort=null
INFO:_____tag=Desktop___________________________________method=startDevicesObserving___________________message => start
```

There has been new emulator in the current environment - ```emulator-5554```.

The main moment is port forwarding.

Next step is a WatchdogThread's start that is responsible to establish socket connection between the client (the host forwarded to device port) and the server (the device).
```
INFO:_____tag=Desktop_________________________________method=startDevicesObserving___________________message => New device has been found: emulator-5554. Initialize connection to it...
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=getDesktopSocketLoad____________________message => calculated desktop client port=11866
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=forwardPorts(fromPort=11866, toPort=8500)_message => started
INFO:_____tag=CommandExecutorImpl_____________________method=execute_________________________________message => adbCommand=adb -s emulator-5554 forward tcp:11866 tcp:8500
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=forwardPorts(fromPort=11866, toPort=8500)_message => result=CommandResult(status=SUCCESS, description=exitCode=0, message=11866
)
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=getDesktopSocketLoad____________________message => desktop client port=11866 is forwarding with device server port=8500
INFO:_____tag=DeviceMirror____________________________method=startConnectionToDevice_________________message => connect to device=emulator-5554 start
INFO:_____tag=DeviceMirror.WatchdogThread_____________method=run_____________________________________message => WatchdogThread is started from Desktop to Device=emulator-5554
```

Further, you can observer a lot of attempts to establish connection between the client and the server.

It's right behavior. Don't worry.
```
INFO:_____tag=DeviceMirror.WatchdogThread_____________method=run_____________________________________message => Try to connect to Device=emulator-5554...
INFO:_____tag=ConnectionServerImplBySocket____________method=tryConnect______________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => current state=DISCONNECTED
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=getDesktopSocketLoad____________________message => started with ip=127.0.0.1, port=11866
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=getDesktopSocketLoad____________________message => completed with ip=127.0.0.1, port=11866
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => updated state=CONNECTED
INFO:_____tag=ConnectionServerImplBySocket____________method=tryConnect______________________________message => start handleMessages
INFO:_____tag=SocketMessagesTransferring______________method=startListening__________________________message => start
ERROR:____tag=SocketMessagesTransferring______________method=startListening__________________________message => java.io.EOFException
INFO:_____tag=ConnectionServerImplBySocket____________method=tryDisconnect___________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=disconnect______________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=disconnect______________________________message => current state=CONNECTED
INFO:_____tag=ConnectionMaker_________________________method=disconnect______________________________message => updated state=DISCONNECTING
INFO:_____tag=ConnectionMaker_________________________method=disconnect______________________________message => updated state=DISCONNECTED
INFO:_____tag=ConnectionServerImplBySocket____________method=tryDisconnect___________________________message => attempt completed
INFO:_____tag=ConnectionServerImplBySocket____________method=tryConnect______________________________message => attempt completed
INFO:_____tag=DeviceMirror.WatchdogThread_____________method=run_____________________________________message => Try to connect to Device=emulator-5554...
INFO:_____tag=ConnectionServerImplBySocket____________method=tryConnect______________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => current state=DISCONNECTED
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=getDesktopSocketLoad____________________message => started with ip=127.0.0.1, port=11866
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=getDesktopSocketLoad____________________message => completed with ip=127.0.0.1, port=11866
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => updated state=CONNECTED
INFO:_____tag=ConnectionServerImplBySocket____________method=tryConnect______________________________message => start handleMessages
INFO:_____tag=SocketMessagesTransferring______________method=startListening__________________________message => start
ERROR:____tag=SocketMessagesTransferring______________method=startListening__________________________message => java.io.EOFException
INFO:_____tag=ConnectionServerImplBySocket____________method=tryDisconnect___________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=disconnect______________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=disconnect______________________________message => current state=CONNECTED
INFO:_____tag=ConnectionMaker_________________________method=disconnect______________________________message => updated state=DISCONNECTING
INFO:_____tag=ConnectionMaker_________________________method=disconnect______________________________message => updated state=DISCONNECTED
INFO:_____tag=ConnectionServerImplBySocket____________method=tryDisconnect___________________________message => attempt completed
INFO:_____tag=ConnectionServerImplBySocket____________method=tryConnect______________________________message => attempt completed
```

When a developer runs the application containing *Device* part of AdbServer and starts this part then the connection is successfully established.
```
INFO:_____tag=DeviceMirror.WatchdogThread_____________method=run_____________________________________message => Try to connect to Device=emulator-5554...
INFO:_____tag=ConnectionServerImplBySocket____________method=tryConnect______________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => current state=DISCONNECTED
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=getDesktopSocketLoad____________________message => started with ip=127.0.0.1, port=11866
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=getDesktopSocketLoad____________________message => completed with ip=127.0.0.1, port=11866
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => updated state=CONNECTED
INFO:_____tag=ConnectionServerImplBySocket____________method=tryConnect______________________________message => start handleMessages
INFO:_____tag=SocketMessagesTransferring______________method=startListening__________________________message => start
INFO:_____tag=SocketMessagesTransferring______________method=startListening__________________________message => IO Streams were created
INFO:_____tag=ConnectionServerImplBySocket____________method=tryConnect______________________________message => attempt completed
INFO:_____tag=SocketMessagesTransferring.MessagesListeningThread_method=run_____________________________________message => start to work
```

And an example of one command execution:
```
INFO:_____tag=SocketMessagesTransferring.MessagesListeningThread_method=peekNextMessage_________________________message => with message=TaskMessage(command=AdbCommand(body=shell input text 1))
INFO:_____tag=ConnectionServerImplBySocket____________method=handleMessages__________________________message => received taskMessage=TaskMessage(command=AdbCommand(body=shell input text 1))
INFO:_____tag=CommandExecutorImpl_____________________method=execute_________________________________message => adbCommand=adb -s emulator-5554 shell input text 1
INFO:_____tag=ConnectionServerImplBySocket____________method=handleMessages.backgroundExecutor_______message => result of taskMessage=TaskMessage(command=AdbCommand(body=shell input text 1)) => result=CommandResult(status=SUCCESS, description=exitCode=0, message=)
INFO:_____tag=SocketMessagesTransferring______________method=sendMessage_____________________________message => where sendModel=ResultMessage(command=AdbCommand(body=shell input text 1), data=CommandResult(status=SUCCESS, description=exitCode=0, message=))
```

#### The device logs
The device with *Device* part is running and waiting host with working AdbServer (*Desktop* part). But no one host exists in the current environment.
```
INFO:_____tag=Device__________________________________method=start___________________________________message => start
INFO:_____tag=Device.WatchdogThread___________________method=run_____________________________________message => WatchdogThread starts from Device to Desktop
INFO:_____tag=Device.WatchdogThread___________________method=run_____________________________________message => Try to connect to Desktop...
INFO:_____tag=ConnectionClientImplBySocket____________method=tryConnect______________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => start
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => current state=DISCONNECTED
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=getDeviceSocketLoad_____________________message => started
```

There has been appropriate host.
```
INFO:_____tag=DesktopDeviceSocketConnectionForwardImplmethod=getDeviceSocketLoad_____________________message => completed
INFO:_____tag=ConnectionMaker_________________________method=connect_________________________________message => updated state=CONNECTED
INFO:_____tag=ConnectionClientImplBySocket____________method=tryConnect______________________________message => start handleMessages
INFO:_____tag=SocketMessagesTransferring______________method=startListening__________________________message => start
INFO:_____tag=SocketMessagesTransferring______________method=startListening__________________________message => IO Streams were created
INFO:_____tag=ConnectionClientImplBySocket____________method=tryConnect______________________________message => attempt completed
INFO:_____tag=SocketMessagesTransferring.MessagesListeningThread_method=run_____________________________________message => start to work
```

And an example of one command execution:
```
INFO:_____tag=Device__________________________________method=execute_________________________________message => Start to execute the command=AdbCommand(body=shell input text 1)
INFO:_____tag=ConnectionClientImplBySocket____________method=executeAdbCommand_______________________message => started command=AdbCommand(body=shell input text 1)
INFO:_____tag=SocketMessagesTransferring______________method=sendMessage_____________________________message => where sendModel=TaskMessage(command=AdbCommand(body=shell input text 1))
INFO:_____tag=SocketMessagesTransferring.MessagesListeningThread_method=peekNextMessage_________________________message => with message=ResultMessage(command=AdbCommand(body=shell input text 1), data=CommandResult(status=SUCCESS, description=exitCode=0, message=))
INFO:_____tag=ConnectionClientImplBySocket____________method=handleMessages__________________________message => received resultMessage=ResultMessage(command=AdbCommand(body=shell input text 1), data=CommandResult(status=SUCCESS, description=exitCode=0, message=))
INFO:_____tag=ConnectionClientImplBySocket____________method=executeAdbCommand_______________________message => command=AdbCommand(body=shell input text 1) completed with commandResult=CommandResult(status=SUCCESS, description=exitCode=0, message=)
INFO:_____tag=Device__________________________________method=execute_________________________________message => The result of command=AdbCommand(body=shell input text 1) => CommandResult(status=SUCCESS, description=exitCode=0, message=)
```

## Additional info

[RU] [Дмитрий Мовчан, Евгений Мацюк — Как начать писать автотесты и не сойти с ума](https://youtu.be/q_8UUhVDV7c?t=1285)

[RU] [Егор Курников — Единственное, что вам нужно для UI-тестирования](https://youtu.be/cTykctRSmuA?t=963)

## Integration

To use AdbServer device library, include the `jcenter` repository to your root `build.gradle` file (if it does not exist already):

```
allprojects {
repositories {
jcenter()
}
}
```

And then add dependency to your module `build.gradle`:

```
androidTestImplementation 'com.kaspersky.android-components:adbserver-device:1.0.0'
```

## Support
Russian support in telegram - t.me/kaspresso

## Contribution Policy
AdbServer is an open source project, and depends on its users to improve it. We are more than happy to find you interested in taking the project forward.

Kindly refer to the [Contribution Guidelines](https://github.com/KasperskyLab/AdbServer/blob/master/CONTRIBUTING.md) for detailed information.

## License
AdbServer is open source and available under the [Apache License, Version 2.0](https://github.com/KasperskyLab/AdbServer/blob/master/LICENSE).