I have a framework with cucumber.
My feature file looks like:
Feature: Test
Background: Launch app
Given Click on app
And app is opened
Scenario: scenario 1
When click on blabla
Then see blabla
Scenario: scenario 2
When click on qwert
Then see qwert
If scenario 1 is failed on Then step, then it goes to scenario 2, but failed on step from Background 'And app is opened'.
Why it not restart app, when go to scenario 2.enter code here
Information that you provided is not enough but i can make a guess.
Background case runs before every scenario, that means, that if scenario 1 failed in, for example, some screen in the application, cucumber will try to Click on app before scenario 2. But, as you can see, there is no app that is available to be clicked. You need to change your step definition of the Click on app, for example add some condition:
if (app.isVisible) {
click();
} else {
//app already launed
}
I think you're struggling to reset the application to its initial state so that other tests would run seamlessly irrespective of previous tests' result. In your example, make sure you close/kill your app by using #After hook. Something like this.
public class Hooks{
static WebDriver driver;
#Before
public void beforeHook(Scenario scenario){
driver = new ChromeDriver(); //initialize with capabilities for your webapp/mobile app respectively.
}
#After
public void afterHook(Scenario scenario){
driver.quit();
}
public static void getDriver(){
return driver;
}
}
public class StepDefinitions{
#Given("click on app")
public void launchApp(){
driver = Hooks.getDriver(); // initialize your app here
}
}
For further references
Related
How can I go to recent apps menu and How to select a particular app from the recents by using Espresso Android Instrumentation Test
Since selecting app from recent apps menu, it need controller over device. I think it can't be done with Espresso alone.
But you can achieve this by using android uiautomator.
fun selectAppFromRecentApps(appTitle:String){
mDevice.pressHome()
mDevice.pressRecentApps()
var uiSelector = UiSelector().className("android.widget.ScrollView") //scroll view listing all recent apps
var count = mDevice.findObject(uiSelector).childCount
for (i in 0 until count step 1) {
val child = UiScrollable(uiSelector.childSelector(UiSelector().resourceId("com.android.systemui:id/task_view_bar").instance(i))).getChild(UiSelector().resourceId("com.android.systemui:id/title")) // app framelayout
val text = child.text
if (text == appTitle) {
child.click()
break
}
if(i==count-1){
throw RuntimeException("App : "+ appTitle +" not found in
recent apps")
}
}
}
Unfortunately VIGNESHs answer did not work for me. I expect different devices to have different implementations of the overview view, or probably it's the Android version.
Anyway the following worked for me on different devices:
getInstrumentation().waitForIdleSync();
mDevice.pressHome();
mDevice.pressRecentApps();
mDevice.waitForIdle();
// If the application is listed, there needs to be an element with a content description
// containing the package name
if (!mDevice.wait(Until.hasObject(By.descStartsWith(getTargetContext().getPackageName())), 1000))
{
fail("Overview did not open");
}
// As the app to be tested was the last one opened, we can simply press the button again.
mDevice.pressRecentApps();
// Wait until the activity under test is back.
// If you skip that, you might be to early, doing further tests.
mDevice.wait(Until.hasObject(By.pkg(getTargetContext().getPackageName())), 1000);
getInstrumentation().waitForIdleSync();
I have a testsuite which has mutiple testcases in a class
every test case is isolated
So when i execute the testsuite class i want to restart the app for every testcase
How do i relaunch application from start for every individual test case in Espresso
Thanks in advance
#Test
public void testcase1() {
//from first screen
}
#Test
public void testcase2() {
//from first screen
}
There is another stack overflow answer that seems to answer this question. If you were looking to do that in Kotlin though I converted the answer to relaunch multiple times for different tests.
#RunWith(AndroidJUnit4::class)
class ExampleEspressoTest {
#get:Rule
val rule = ActivityTestRule(
activityClass = MainActivity::class.java,
initialTouchMode = false,
launchActivity = false) //set to false to customize intent
#Test
fun testCustomIntent() {
val intent = Intent().apply {
putExtra("your_key", "your_value")
}
rule.launchActivity(intent)
//continue with your test
}
}
If you need to start a method/test and when it's finished clear data and start the next one, you should use commands.
Look at this documentation: https://developer.android.com/studio/test/command-line
I'm using this command:
./gradlew testVariantNameUnitTest --tests *.sampleTestMethod
There could be several ways to do this but we wanted a way that works both locally as well as google fire base test lab, so ended up with using configuration in build.gradle file under default config.
defaultConfig{
testInstrumentationRunnerArguments clearPackageData: 'true'
}
Reference: https://developer.android.com/training/testing/junit-runner#ato-gradle
Also you use these runner arguments for configuring different tests you wanted run based on build variants or other config options, look at my post if you want more detail.
Lately, I have been trying to add static interstitial ads into my Unity game. For some reason, I could not get the system to show anything, or even react to me. After trying to work with the base Chartboost plugin, I tried to match a tutorial that I was following and purchased Prime31's Chartboost plugin and have been using that. However, neither the base plugin, nor Prime31's plugin, seem to be allowing me to show any ads. The code is pretty much done inside a single object, and it seems simple enough.
public class Advertisement : MonoBehaviour {
public string chartboostAppID = "5461129ec909a61e38b1505b";
public string chartboostAppSignature = "672b3b34e3e358e7a003789ddc36bd2bc49ea3b5";
// Use this for initialization
void Start () {
DontDestroyOnLoad(this.gameObject);
ChartboostAndroid.init (chartboostAppID, chartboostAppSignature, true);
ChartboostAndroid.cacheInterstitial(null);
}
void OnLevelWasLoaded(int level) {
ChartboostAndroid.cacheInterstitial(null);
if(Application.loadedLevelName == "Network Lobby") {
showAds();
}
}
public static void showAds() {
Debug.Log("Showing ad");
ChartboostAndroid.showInterstitial(null);
}
}
As you can see, it's pretty straightforward. This object is created at the game's splash screen, which appears only once, and it's never destroyed until the program ends. The goal is, whenever I enter the lobby scene, I want to see an ad before going to the lobby's menus. As it is, I do see the log printing "Showing ad", so I know the function is being called. However, nothing appears. Do I need to disable the GUI system first? Is there a step I'm missing?
I have already performed the following steps:
I have created and registered the app with chartboost, as well as double and triple checked the AppID and App Signature.
I have created a publishing campaign and registered it to the app.
I double-checked the orientation and confirmed that it's correct.
I registered this specific device as a test device.
The tutorial showed a call to ChartBoostAndroid.OnStart(), but there was no function like that for me to call. Perhaps that is from an older version?
I emailed Chartboost support and have not heard from them yet. I do not have that much time on this project, so if anyone can offer help, I'd appreciate it.
Is it possible to have something like this? Either with Android/Robotium test frameworks or any other solutions
public void testAll() throws Exception {
test_001_LoginActivity();
test_002_MainActivity();
}
public void test_001_LoginActivity() throws Exception {
startActivity();
test_001_LoginActivity_001_emptyUsername();
test_001_LoginActivity_002_emptyPassword();
test_001_LoginActivity_003_incorrectValues();
test_001_LoginActivity_004_correctValues(); // MainActivity is opened on success
}
public void test_002_MainActivity() throws Exception {
test_002_MainActivity_001_profile();
test_002_MainActivity_002_list();
test_002_MainActivity_003_logout();
}
The idea is to have test_001_LoginActivity() and test_002_MainActivity()contain all the corresponding activity test without recreation of the activities. And to have a result displayed like that:
test_001_LoginActivity() - OK
--->test_001_LoginActivity_001_emptyUsername() - OK
--->test_001_LoginActivity_002_emptyPassword() - OK
--->test_001_LoginActivity_003_incorrectValues() - OK
--->test_001_LoginActivity_004_correctValues() - OK
test_002_MainActivity() - NOK
--->test_002_MainActivity_001_profile() - OK
--->test_002_MainActivity_002_list() - NOK
--->test_002_MainActivity_003_logout() - OK
Which means that all tests for LoginActivity are passed successfully; test_002_MainActivity_002_list() test failed for MainActivity, but test_002_MainActivity_003_logout() test was passed(since activity was not recreated)
I'm new to testing, so maybe I'm getting it wrong and tests are intended to be executed for a brand new activity instance always?
What your are trying to do might be possible if you rename all test_00X_METHOD methods becuase currently it will go to total mess because "test" prefix before a methods has a special meaning for jUnit Framework - beside all will be executed by you from testAll() also all methods will be executed latere seperately as jUnit run all methods with "test" prefix as seperate test case and application is even restarted between those methods. So it should works fine if you throw away all "test" prefixes but keep it for testAll(). And you needn't "startActivity()" method at the begining of test_001_LoginActivity() because Activity is automaticaly started - which activity? Activity you passed as type parameter to this class: http://developer.android.com/reference/android/test/ActivityInstrumentationTestCase2.html.
I hope this answer is useful for you.
Krzysiek,
Bitbar Software Engineer
I am writing automated testing code (using ActivityInstrumentationTestCase2) to test an app that involves in-app billing version 2 (subscriptions). I need help on figuring out how to programmatically get my testing code to click on the "Accept and Buy" button that appears inside the "Pay with credit card/Secured by Google Wallet" dialog which is supposedly created by some Google SDK code.
I can get the testing code to click on other buttons that are created by my own code/acitivty, usually by accessing the buttons from its parent activity or view, and then call the .performClick() method on the button. But this "Buy" button is not reachable from any activities as far as I know.
It appears this dialog may be created by com.google.android.finsky.activities.IabActivity based on the logcat output. I used an ActivityMonitor watching this activity, but it was never triggered. If you can help either directly, or point me to the relevant Google SDK source code that's responsible for creating the "Pay with credit card" dialog or the source for the com.google.android.finsky.activities.IabActivity class, I'd be very grateful.
Normally you can't instrument Activities outside of your own package.
You'd have to use the UI Automator framework to click the Buy button.
Thanks to Christopher. I managed to use UI Automation to get the effect I want. I had to write a shell script to call my Instrumentation Test first, which brings up the Buy dialog. Then call
adb shell uiautomator runtest to launch the UI automation code to click on the "Buy" button. Not sure how to sync between them so I just use some sleep code to time the click. Here is the UI automation code:
UiDevice dev = getUiDevice();
// wait for buy button to appear
while (true) {
try {
Thread.sleep(2000l);
UiObject okButton = new UiObject(new UiSelector().text("Accept & buy").className("android.widget.Button"));
okButton.click();
break;
} catch (Exception e) {
}
}
dev.waitForIdle();
Using uiautomator, this is the best I got:
device.findObject(new UiSelector().resourceId("com.android.vending:id/continue_button")).click();
Here are suggestion for making Testcase for Button click in android.
You need to make ActivityInstrumentationTestCase2 for your Activity then do following .
Initialize your button in
protected void setUp() throws Exception {
super.setUp();
mainActivity = getActivity();
btnAcceptBuy= (Button) mainActivity.findViewById(R.id.btnaccept_buy);
}
public void testFragmentKeypad(){
AppLog.showLogE("TEST", "Keypad");
TouchUtils.clickView(this, btnAcceptBuy);
}
By this way you can perform click testing of your button in android.
UiAutomation uiAutomation = new UiAutomation(Looper.getMainLooper(), new UiAutomationConnection());
uiAutomation.setOnAccessibilityEventListener(new UiAutomation.OnAccessibilityEventListener() {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == TYPE_WINDOW_STATE_CHANGED) {
if ("com.google.android.finsky".contentEquals(event.getPackageName())) {
if ("com.google.android.finsky.activities.IabActivity".contentEquals(event.getClassName())) {
final List<AccessibilityNodeInfo> accessibilityNodeInfosByViewId = event.getSource().findAccessibilityNodeInfosByViewId("<package name>:id/<control id>"); // find by layout inspector
if (accessibilityNodeInfosByViewId.size() > 0) {
accessibilityNodeInfosByViewId.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
}
});
uiAutomation.connect();
//release when exit
uiAutomation.disconnect();