Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Make it possible to consume Espresso server as a library #1020

Merged
merged 4 commits into from
Jul 10, 2024

Conversation

technoir42
Copy link
Contributor

Context

Espresso server has to be built with the correct versions of plugins, dependencies and signing keys that match the app it will be instrumenting. One way to do so is to build the server from this repo, passing a relatively long list of Gradle properties.

The idea

Instead, we want to consume Espresso server as a library, apply dependency constraints to align the versions of dependencies, and embed it in either androidTest component of the app or in a standalone test module under the same
Gradle project. The library only has to expose a single method for starting a server and TestRule for Compose support.
This way, the Espresso server APK will be built with the correct versions of AGP, Kotlin and dependencies automatically.
If the app is obfuscated, we can also use slackhq/keeper to infer the obfuscation rules.

Example

Standalone test module:

plugins {
    id "com.android.test"
}

android {
    namespace = "com.my.espresso.server"

    defaultConfig {
        testApplicationId = "io.appium.espressoserver.test"
        minSdk = 21
        targetSdk = 34
    }

    targetProjectPath = ":app"
}

dependencies {
    implementation "androidx.test:runner:1.6.0"
    implementation "io.appium.espressoserver:library:2.44.1"
}

The test that should reside on the consumer side:

package com.my.espresso.server

import android.annotation.SuppressLint
import androidx.test.filters.LargeTest
import io.appium.espressoserver.lib.http.Server
import org.junit.Rule
import org.junit.Test

@LargeTest
class EspressoServerRunnerTest {
    @get:Rule
    val server = Server()

    @Test
    fun startEspressoServer() {
        server.run()
    }
}

Build both the app and Espresso server:

./gradlew :app:assembleDebug :espresso_server:assembleDebug

Copy link

linux-foundation-easycla bot commented Jul 4, 2024

CLA Signed

The committers listed above are authorized under a signed CLA.

@mykola-mokhnach
Copy link
Contributor

Thank you @technoir42

Please update failing integration tests and also prepare a separate document which describes in details how to use this driver as a library

@KazuCocoa
Copy link
Member

package.json also needs to be updated to publish necessary code via npm.
https://github.com/appium/appium-espresso-driver/blob/master/package.json#L52

@technoir42 technoir42 changed the title Make it possible to consume Espresso server as a library feat: Make it possible to consume Espresso server as a library Jul 8, 2024
@technoir42
Copy link
Contributor Author

@mykola-mokhnach I might've fixed functional tests, can you approve the workflow please?

@mykola-mokhnach
Copy link
Contributor

@mykola-mokhnach I might've fixed functional tests, can you approve the workflow please?

Done. Thanks.

Where could I find the document that describes how to use the source as a library?

@technoir42
Copy link
Contributor Author

For now, the library cannot be consumed externally, even via JitPack. I will add publishing to a Maven repository in a follow-up PR if that's fine with you. I did however verify that the solution works via a fork published to JitPack.
I'm already working on a sample project on how to consume Espresso server as a library and run the server against an obfuscated app, then I will write a doc how to do so.

@KazuCocoa
Copy link
Member

It would probably make sense to increase the major version as the structure/usage changes. (it just needs to add "BREAKING CHANGES" in the commit message, so this is a note for us when we merge this thing)

I'll take a look and do a bit of testing with this branch tonight or tomorrow for existing usage.

For Maven, maybe we need to do similar thing to what currently does in https://github.com/appium/java-client then (name space etc)

@technoir42
Copy link
Contributor Author

technoir42 commented Jul 9, 2024

@KazuCocoa this shouldn't affect existing usages, so it's more of an internal structure change than a breaking change. If you notice any change in behaviour for existing users, I can revert it.
One small breaking change that I recall is that I removed appiumZipAlign property because it has no effect anymore. I can restore it if necessary. Or I can remove it in a separate commit/PR to ensure the removal would end up in the changelog.

For Maven, maybe we need to do similar thing to what currently does in https://github.com/appium/java-client then (name space etc)

Thanks for the tip, I'll look into that.

@mykola-mokhnach
Copy link
Contributor

mykola-mokhnach commented Jul 9, 2024

I also did not mention any breaking things. It would be interesting for me too see how the "library" scenario is supposed to work. Are we going to use the bundled module separately from the espresso driver or it could still be a part of the ecosystem, like in the flutter integration driver?

@KazuCocoa
Copy link
Member

KazuCocoa commented Jul 9, 2024

Sure, I just thought this could be kind of a major version update with a new usage for the espresso driver itself, so not breaking change or small feature addition but to show this has a major usage update: current existing method to run a single server and interact with the app under test via instrument, and let users to integrate this Appium espresso server in their own espresso module to create custom espresso server by them.

So, with this lib method, a user could build their own espresso server that has Appium Espresso functionality and their own something like a mock server as one package without forking this repo (with appium:skipServerInstallation as caps for this driver for example), or could run the espresso server as part of espresso tests (then this driver might not be necessary?). The target app could still be a release module/debug module.

}

dependencies {
// additionalAppDependencies placeholder (don't change or delete this line)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think api is better for here than implementation?

? 'implementation'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that transitive implementation dependencies don't get packaged into the instrumentation APK, and R8 minification fails due to missing classes. I faced this with a standalone test module. However api dependencies get packaged as expected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KazuCocoa I changed the script to add additionalAppDependencies as api ones.

Copy link
Member

@KazuCocoa KazuCocoa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, overall 🚀 I did a test on my local with a couple of espresso configs, and another test suite.

@technoir42
Copy link
Contributor Author

technoir42 commented Jul 10, 2024

I added BREAKING CHANGE footer about appiumZipAlign removal in the first commit.

So, with this lib method, a user could build their own espresso server that has Appium Espresso functionality and their own something like a mock server as one package without forking this repo (with appium:skipServerInstallation as caps for this driver for example), or could run the espresso server as part of espresso tests

Yep, we build and install the app and Espresso server APK ourselves, then use an Appium client with appium:skipServerInstallation capability.

@technoir42
Copy link
Contributor Author

technoir42 commented Jul 10, 2024

Here's a sample project to show this in action.
I will work on publishing and documentation now. Since the library is not consumable externally yet, updating the docs after the publishing is ready might make more sense. @mykola-mokhnach @KazuCocoa wdyt?

Copy link
Member

@KazuCocoa KazuCocoa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm good at proceeding documentation etc after this pr merge.

For publishing, maybe starting from jitpack would be good, then maven. (I haven't checked anything to run this repo on jitkack right now tho)
https://github.com/appium/java-client

@mykola-mokhnach mykola-mokhnach merged commit 1bf4a92 into appium:master Jul 10, 2024
12 checks passed
github-actions bot pushed a commit that referenced this pull request Jul 10, 2024
## [3.0.0](v2.44.2...v3.0.0) (2024-07-10)

### ⚠ BREAKING CHANGES

* `appiumZipAlign` Gradle property has been removed as it didn't have any effect

### Features

* Make it possible to consume Espresso server as a library ([#1020](#1020)) ([1bf4a92](1bf4a92))
Copy link

🎉 This issue has been resolved in version 3.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@KazuCocoa KazuCocoa added the size:M contribution size: M label Sep 6, 2024
@KazuCocoa KazuCocoa added size:L contribution size: L and removed size:M contribution size: M labels Sep 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
released size:L contribution size: L
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants