I'm on a team with multiple developers. We're using JUnit5 via android-junit5 and tests written using the #Test annotation from the org.junit package as opposed to the org.junit.jupiter.api package are excluded from gradle's test reporting. I'd like to, if possible, outright prevent developers from using org.junit. Is there a way to do this using gradle? I'd like to achieve this particular solution and not a workaround as there are other instances that we'd like to prevent users from using a given package (java.time.* in Java 8 vs ThreeTenABP)
Thank you
One way of approaching the problem could be to create a Jar that contains only the allowed APIs. You could then upload that jar to an repository and ask developers to use it as a testCompileOnly dependency while keeping the original jar as a testRuntimeOnly dependency.
This will guarantee that test code cannot access the forbidden classes/packages since it will not see them during compilation.
Related
I have confusion that how the android packaging works with library, Say i am used some kotlin experimental apis in my application.I have published the application, Say After the production the experimental api which i have used have major change.
Does my app which is already published get affected?
Can anyone resolve my confusion?
Android Packaging are the group of libraries that you used for your particular task.
Suppose you want to use retrofit Networking library in your project, However, you need to use some callback method and those callback methods will import via package.
Here one more practical example, you want to work with Java then JAVA SDK here, you have to set in environment variable then you use methods in your framework.
Now let me come of Effection, so yes some libraries got update and some deprecate due to advancement feature. Yes, it impacts on your project. not in meantime but yes in future if there is any advance feature.
I would like to be able to have common test code in a library module of my android projects, so that the different apps in the project can use them.
The problem is, apps cannot import classes from <library>/src/androidTest/java, and if I move that at code into src\main, it would have to move dependencies from androidTestCompile to compile (more dependencies to the release build).
The only solution right now is to create a separate library to hold the shared test classes, however this has the downside of adding a new library to the project structure, which is not that big a deal, but I'd like to know nonetheless if there are better solutions.
I'd rather implement a Gradle hack at this point if any Gradle (Android plugin) wizards out there can help me find one.
Since I got no answers, I might as well answer my own question.
I ended up using the solution I already mentioned in my question:
Create a library with shared test classes (not actual test cases, but common code to be used in the final ones) under src/main and import it with androidTestCompile or androidTestImplementation for recent gradle versions.
Got a solution that doesn't involve adding a module? I won't accept my own answer since it doesn't exactly answer the question.
If you have code (test or otherwise) that can be reused across multiple modules, the appropriate thing to do is exactly what you've done: put it in it's own module and import it into the other modules.
The small overhead of creating a new module is giving you a lot of power. It allows you to manage its build without having to change every dependent module's build.
Any other option I've tried (creating a single module that contains all modules' tests, e.g.) ends up being a much bigger headache and a dependency nightmare.
I like the Kotlin REPL in Idea / Android-Studio - but as an Android Developer I often run into Stub! problems here. When writing unit-tests I am using unmock to work around this problem. Is there a way to use the same method used there for the Kotlin REPL plugin?
[
All android (and java.lang.*) classes are placeholders in an Android project. This is because android does not use standard java class files to store the compiled code and there is no way to directly run this code on a computer.
You simply can't use the REPL with android classes, they will only exist on an actual device or emulator.
If you do not care about correctness, then you can use Robolectric's implementation of Android by adding it as a dependency to the project.
To make sure it does not collide with the actual implementation you should probably do this with a separate module dedicated to the REPL.
Robolectic's dependency used by unmock is: org.robolectric:android-all:7.1.0_r7-robolectric-0
The problem is that the Kotlin REPL in IDEA is provided by the Kotlin IDEA plugin, which has no notion of Android per se, but only looks at what's in the classpath, which in this case is the android.jar containing the stubs that throw the exception you mentioned.
Using unmock or even the integrated Android support for removing exceptions from the stubs in tests (see here at the end of "Mock Android dependencies") won't work as that only affects your Gradle build.
The only solution I can think of is to either open an issue on the Kotlin tracker or dig through the source code of the REPL function in the Kotlin plugin and send a Pull Request.
I received some legacy code of app (not developed by me, but by some other team, with no documentation), which has almost 20+ dependencies, in build.gradle.
Now, I wanted to clean up unused Libraries/dependencies, by removing them from build.gradle
I searched on Google and came across this project for resource shrinking. But it seems to be used for removal of resources that are unused, at build time, in the packaged app and this also removes resources from libraries you are depending on if they are not actually needed by your application.
Also, I use ProGuard, for obfuscation and shrinking in conjunction with shrinkResources true in build.gradle
My intention is to remove unused Libraries/dependencies from build.gradle itself, without breaking app functionality.
Is there a way or tool which shows which library is safe to remove without breaking the app functionality?
By 20+ dependencies you don't need any tooling and can do a manual check.
I would proceed like this:
Comment out all dependencies and check what fails (see below)
Uncomment the dependency that causes the failure
Repeat
This way you might also notice dependencies that are seldom used or can be replaced with standard libraries or other libraries that you use in the project.
Here are the things that will indicate you that a dependency is required (in the order of slowing down the feedback loop):
compilation errors
unit test errors
integration / system / end-to-end / device test errors (whatever you use and call them)
application functionality at runtime
application performance at runtime
Runtime dependencies can be especially tricky. For example, your code might not depend on a library, but this library provides a runtime implementation for some other library you depend on. Removing such a dependency will only be visible at runtime as missing functionality or performance issues.
Instead of commenting out all dependencies I would go the other way around - comment out one dependency at a time and see what breaks. This way you would also get a grasp of use-cases of all dependencies because the IDE will point you to the place where code broke. If nothing breaks after commenting out a dependency you'll know that it's not used. Another thing you could potentially do is analyze an unobfuscated release .apk where all unused dependencies will be missing but package structure will be preserved.
If you mean that finding unused library or import, you can easily see with "Ctrl + alt + shift + i" and type "unused import"
You can see now all unused imports.
Finding libraries and resources used in an Android app comes up in several contexts.
For the apps published in Google Play, AppBrain maintains reverse lookups, from the library to the more popular apps that use it. For example, apps using a newish 2D game library Godot.
Apktool will decode the APK directly.
The author instead wants to find (unused) resources, starting from the source code and the build process. Gabriele Mariotti above links to the question, whose accepted answer provides detailed information on use of minifyEnabled and shrinkResources in Gradle configuration.
Review Shrinking Android app and ProGuard vs R8.
I would like built a closed source android library using the Gradle. My library has some dependencies to open source projects. How should I structure my library? Can I use gradle?
Can I use gradle?
Short answer:
Yes.
Long answer:
I would assume that your library is packaged as aar (contains resources and compiled bytecode).
First thing you need to know is that at the moment of writing this post there is no way to create fat-aar libraries, which means that you'll have to distribute dependencies of your library separately. The most convenient way to do that, in my opinion, is to generate pom.xml file and publish your library on Maven repository (maven plugin can do all of that), so clients will just fetch all dependencies themselves. Since it is a "private" library, that could be your company's closed repo by access rights (in simple words - create special user for your repo and share password with interested parties).
One downside here is that all dependencies will be exposed in pom.xml and you won't be able to obfuscate them. Personally, I don't think that this is an issue.
Moreover, you get the huge advantage of being able to deploy build automatically and let clients use snapshot versions of the library. This is extremely helpful when you're trying to fix issues and want to deliver them to users fast. On client's side, all they need to do is either just update version in their build.gradle or just re-sync project in case if they were using snapshot.
Second thing. Since your library is closed source, you need to run proguard to obfuscate everything but public interface of your library (all public methods which are exposed to end user).
Remember, that even after obfuscation your code still can be decompiled and all string literals are still there. So, although it was said million times already, avoid storing any critical data in the library (such as passwords, keys, etc.). It is not as hard to extract it as you might think it is: https://www.youtube.com/watch?v=X28Oogg2Q3k
Third thing. I highly suggest you to create internal test project (as a gradle submodule) which will use your library, so you will be sure that you're not making any breaking changes.
Hopefully this answer made things at least a bit easier for you.