Releases: KasperskyLab/Kaspresso
Kaspresso 1.2.0: AdbServer
Autotest AdbServer
AdbServer is a part of Kaspresso
We've decided to merge AdbServer into main Kaspresso repository. AdbServer is very tied with Kaspresso and there is no mind to maintain two separate repositories. Further support and development should be easier.
New AdbServer logging
AdbServer logging is more enjoyable, suitable, and understandable now.
Take a look at the example of logs from the Deskop:
INFO 10/09/2020 11:37:20.185 desktop=Desktop-25920 device=emulator-5554 message: The attempt to connect to Device was a success
You can see the type of a message, date and time, the desktop executing the message and the emulator giving the task, and the message.
Another example of logs from the Device:
2020-09-10 12:24:27.427 10349-10378/com.kaspersky.kaspressample I/KASPRESSO_ADBSERVER: The result of command=AdbCommand(body=shell su 0 svc data disable) => CommandResult(status=SUCCESS, description=exitCode=0, message=, serviceInfo=The command was executed on desktop=Desktop-30548)
Here is very useful information about where the command was executed. In this example, the command was executed on Desktop-30548.
You can choose an appropriate type of logging: VERBOSE
, DEBUG
, INFO
, WARN
, ERROR
. INFO
is a default type providing all basic logs. In some cases VERBOSE
and DEBUG
modes could be useful too.
Also, a lot of potential bugs and issues were fixed. All information is available in AdbServer wiki.
Fixes and improvements
- Updated
Network
implementation is able to turn on/off network even without running AdbServer. - Improved
compose
with extended API. - Fixed
Logcat
implementation that required AdbServer to be run before every test. StepInfo
is available in everystep
now.- Added more flexible way to struct folders after screenshot tests.
- Bumped library versions.
- Improved samples stability.
- Many small bugs has been fixed.
Breaking changes
- We've totally reworked AdbServer and Kaspresso 1.2.0 works only with new
artifacts/adbserver-desktop.jar
The old versionartifacts/desktop_1_1_0.jar
is also available for use with older versions of Kaspresso. - If you use
device.logcat
in your tests, you should calldevice.logcat.disableChatty
in thebefore
section of your test.
In previous version of Kaspresso,device.logcat.disableChatty
was called automatically during initialization. This resulted in the need to always run AdbServer before tests.
Kaspresso 1.1.0: Kautomator
Wrapper over UI Automator: Kautomator
We are happy to announce a new unique Kotlin DSL wrapper over UI Automator: Kautomator!
Let's consider the main features.
Speed
The most amazing feature of Kautomator is an incredible boost of UI Automator. Just have a look at the video below:
The left video is a boosted UI Automator, the right video is a default UI Automator.
All details are available here.
Readability
Have a look at a typical piece of code written with UI Automator:
val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
val uiDevice = UiDevice.getInstance(instrumentation)
val uiObject = uiDevice.wait(
Until.findObject(
By.res(
"com.kaspersky.kaspresso.sample_kautomator",
"editText"
)
),
2_000
)
uiObject.text = "Kaspresso"
assertEquals(uiObject.text, "Kaspresso")
And just evaluate a Kautomator API that is doing the same thing:
MainScreen {
simpleEditText {
replaceText("Kaspresso")
hasText("Kaspresso")
}
}
You can find a comprehensive Kautomator tutorial here.
Flaky safe
By default, Kaspresso provides a rich set of interceptors for Kautomator that prevent flakiness of UI Automator. How does it work? You are welcome to read here and here.
Let's evaluate multi-stage protection from flakiness in UI Automator:
- Attempt to scroll a parent layout to make the View (
UiObject2
) visible. - Attempt to reload
UiObject2
byBySelector
. - Attempt to suppress android system dialogs if they exist.
- Attempt to repeat failed action for 10 seconds.
Conclusion
Forget your pain, forget your suffering. Just enjoy writing stable and fast tests even though these tests are using UI Automator under the hood.
What else?
Diff in 380 commits contains not only Kautomator =)
Have a glance at some sweet features and changes.
Tests for upgrade scenarios are possible now
Yep, a developer/tester can automate upgrade scenarios using Kaspresso now.
Check the example to learn how to do it.
GDPR check
If you have not heard about GDPR and high-profile lawsuits then you are lucky. But, if your application works in Europe then it's so important to enable/disable all analytics/statistics according to acceptance of the agreements.
One of the most reliable ways to check analytics/statistics sending is to verify logcat where all analytics/statistics write their logs (in debug mode, sure).
That's why we have created a special Logcat
class providing a wide variety of ways to check logcat. Please, observe the example and save money of your company =)
Continuously
Kaspresso provides a new continuously
method that can be useful for your tests. As opposed to flakySafely
, it does not skip the last attempt after the first success and throws inner exception outside as soon as it was thrown. It can be especially helpful for checking negative scenarios.
continuously {
dialogTitle {
doesNotExist()
}
}
Check the source code and example.
Compose
We've updated and extended compose functionality.
The main changes are the UI Automator support and the keyword then
adding:
compose {
// the first potential branch when ComplexComposeScreen.stage1Button is visible
// here, Espresso is used under the hood
or(ComplexComposeScreen.stage1Button) {
isVisible()
} then {
// if the first branch was succeed then we execute some special flow
step("Flow is over the product") {
ComplexComposeScreen {
stage1Button {
click()
}
stage2Button {
isVisible()
click()
}
}
}
}
// the second potential branch when UiComposeDialog1.title is visible
// just imagine that is some unexpected system or product behavior and we cannot fix it now
// here, UI Automator is used under the hood
or(UiComposeDialog1.title) {
isDisplayed()
} then {
// if the second branch was succeed then we execute some special flow
step("Flow is over dialogs") {
UiComposeDialog1 {
okButton {
isDisplayed()
click()
}
}
UiComposeDialog2 {
title {
isDisplayed()
}
okButton {
isDisplayed()
click()
}
}
}
}
}
But remember, compose
is useful in cases when we don't know an accurate sequence of events and can't influence it. Such cases are possible when a test is performed outside the application. When a test is performed inside the application we strongly recommend to make your test linear and not to put any conditions in tests that are possible thanks to compose
.
For more information, please check the documentation, the example and some additional possibilities.
Increased common timeouts
We have decided to increase all default timeouts from 2 seconds to 10 seconds.
Usage of UI Automator has been the main reason for this decision.
BaseTestCase and BaseTestContext improvements
TestAssistantsProvider
We have introduced a special provider that is available via BaseTestCase
and BaseTestContext
:
interface TestAssistantsProvider {
val device: Device
val adbServer: AdbServer
val testLogger: UiTestLogger
val params: Params
}
If you have forgotten what BaseTestCase
and BaseTestContext
mean then let me remind you:
@RunWith(AndroidJUnit4::class)
class SimpleTest : TestCase() { <===== TestCase is an inheritor of BaseTestContext
<===== TestAssistantsProvider is available
// ....
@Test
fun test() =
before { <===== a lambda with receiver where receiver is BaseTestContext
// .... <===== TestAssistantsProvider is available
}.after { <===== a lambda with receiver where receiver is BaseTestContext
// .... <===== TestAssistantsProvider is available
}.run { <===== a lambda with receiver where receiver is inheritor of BaseTestContext
// .... <===== TestAssistantsProvider is available
}
}
It might be useful when a developer wants to put some common code into separate classes. But this common code interacts with mentioned properties like device
, adbServer
, testLogger,
params`. So, your code refactoring will be easier.
beforeEachTest/afterEachTest
Sometimes, a developer wishes to put some actions repeating in all tests before/after into a single place to simplify the maintenance of tests. You can make a remark that there are @beforeTest
/@afterTest
annotations to resolve the mentioned tasks. But the developer doesn't have access to BaseTestContext
in those methods. That's why we have introduced special default actions that you can set in the constructor by Kaspresso.Builder
.
The example of how to implement default actions in Kaspresso.Builder
is:
open class YourTestCase : TestCase(
kaspressoBuilder = Kaspresso.Builder.advanced {
beforeEachTest {
testLogger.i("beforeTestFirstAction")
flakySafety { device.network.enable() }
flakySafety { device.language.switchInApp(FRENCH) }
}
afterEachTest {
testLogger.i("afterTestFirstAction")
}
}
)
The more detailed info is available here.
Enricher
A developer can also extend parametrized tests functionality by providing MainSectionEnricher
in BaseTestCase
or BaseTestCaseRule
. The main idea of enrichers - allow adding additional test case's steps before and after the main section's run
block.
It looks like:
class LoggingMainSectionEnricher : MainSectionEnricher<TestCaseData> {
override fun TestContext<TestCaseData>.beforeMainSectionRun(testInfo: TestInfo) {
testLo...
Minor fixes. Artifactory delivery
Minor fixes for correct artifactory delivery
Initial Release
Initial Release with the core functionality of Kaspresso.
Please observe README file for additional info.