Determine fragment change while espresso testing - android

I'm testing my application in android composed of 1 main activity and multiple fragments inside in which we navigate.
For my tests I use espresso, and after a click on a particular button, I want to check if the current fragment has changed or not (the part with the button is ok).
So, how can I do in espresso to check if the fragment is still the same than before the click on the button?

If you really want to do this, you can do
FragmentManager fragmentManager = getActivity().getFragmentManager()
and get information about the backstack from fragmentManager. If your fragment has a tag, you could assert that findFragmentByTag(tag) returns something non-null.
But it's normally better to make assertions about the view hierarchy. It's what Espresso was designed for, and it's more in the spirit of black-box testing.
So I would suggest finding some distinguishing feature of the new fragment, such as the page title if there is one, and asserting that that view is present using the usual Espresso methods, e.g.
onView(withText("Page Two Title")).check(matches(isDisplayed()));

Related

Testing fragments that access views of the activity they are embedded into

I want to create a single activity app with multiple fragments and a favorite action button.
Since I need the favorite action button on every fragment, and it should always be in the same position, the button is part of the activities layout. Basically like the "Basic Activity"-Project in Android Studio.
The different fragments set their own onClickListener and thus need to reference the favorite action button, which works fine when running the app.
val fab: FloatingActionButton = activity?.findViewById(R.id.fab)
fab.setOnClickListener { ... }
But when doing isolated espresso tests, I obviously get a null pointer exception when the fragment tries to set the onClickListener.
As far as i can see, I now have the following possible solutions for the problem:
I could change the production code to make the favorite action button optional, and always check for null before setting the onClick-Listener
I could change the test to not test the fragment in isolation but instead with the activity.
I test the activity instead of the fragments.
Since my goal is to avoid nullables, solution 2 and 3 appear to be better than solution 1. But solution 1 appears to be the easiest of the three.
What is the best practice to test fragments in a single activity app that shares some controls via the activity?

UI tests on each Fragment Android

I'd like to start implementing UI Tests on each of My Fragments. I just have some Math formulas to verify in each Fragment.
Let's say that from Fragment A I have to go to Fragment B and then to Fragment C(I want to test if each of Fragment's C EditText text changes if a certain button gets clicked).
I Would like to don't go throughout all of the passages to arrive to Fragment C.
I've already installed Espresso using Gradle, but what to do After? Please provide a Step by step implementation.
Thank you in Advance.
Maybe this would be helpful: https://stackoverflow.com/a/27370190/7861694
Or/If you using Espresso I recommend the second option - add a unique id for one element in your fragment layout. https://developer.android.com/reference/android/R.id.html

How to use Fragments

I'm trying to wrap my head around when exactly I should use Fragments and if I'm going to use them how to do so properly.
To my understanding Fragments should be used if you want a more flexible UI as it will be easier when rotating the device and easier to have your layout work with multiple screen sizes.
It seems to me that it is good to use them because you could have an app with ONE activity and multiple Fragments so the activity will be able to get calls from callbacks while the Fragments change what the user is seeing and interacting with. If I were to compare two apps, one made with Activities and the other with Fragments I would imagine to see something like this:
Activity app has a log in screen. The user can log in and it brings them to the main menu (New Activity). Once there they select the Friend button which brings them to a new Friend activity.
Fragment app has an Activity that loads the Log in Fragment into it's FrameLayout. The Log in Fragment allows the user to log into their account. Once it logged in, it replaces the Log in Fragment in the FrameLayout with the Main Menu Fragment. User presses Friend button, it opens the new Friend Fragment in the Activities FrameLayout. In this case all the work is being done in the Fragments but the Activity is just really holding them.
Please tell me why this is the incorrect use... or why this is correct.
Cheers
Take a look at the official Fragments doc. Short answer: always use Fragments. Fragments are better for reusability, flexibility, etc., etc.

Android floating view across activities

Requirement
I have an application with 2 activities, say A and B, with navigations like A->B and B->A (on back press). My requirement is
I want a view/layout floating on screen, irrespective of which
activity is currently visible. I inflate this view on app
start(onCreate of activity A), it remains static on screen during the
transition from A->B and when B is onscreen.
So naturally this view should be inflated only once (when app starts,
onCreate of A).
What I found out
I did some searching, and from what I could find, there are 2 methods to reuse layout in android
using <include>
It just seems like a tool to write xml code of commonly used UI elements. It gets inflated every time it is used in a parent layout.
using ViewStub
I did some research on using ViewStub and It also seems a way to reuse code segment in many layouts. It also need to be inflated every time we use it in a layout except it gets inflated only when we make them visible at run time.
Another hint of my requirement
For people familiar with iPhone development you can add view's to UIWindow, which stays there irrespective of which UIViewController is currently active. I want exact behavior in my application.
My original setup
I am targeting android 2.1 and above. It seems Fragment is available from API level 11 (android 3.0) and above. One option is to use android compatibility library that enables usage of Fragment in older versions. I am currently researching on that now. But I also would like to know if there is any other methods available to fulfill my requirement, rather than change my entire project and use fragments.
I have around 30 odd activities in my application and I want this layout floating over all of them. I just made out a test case with 2 activities to make the question simple and easy.
Solution 1: FrameLayout
I think what you want to use is the FrameLayout. FrameLayout is designed to block out an area on the screen to display a single item. Child views are drawn in a stack, with the most recently added child on top.
http://developer.android.com/reference/android/widget/FrameLayout.html
Then read here about the back stack that you could use in your activity to flip back and forth between the activities using the back button:
http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html
Solution 2: Fragment Transactions
Rather than code two separate Activities, code a single Activity with two Fragments. Here is a blurb from the Fragments documentation:
"A fragment must always be embedded in an activity and the fragment's lifecycle is directly affected by the host activity's lifecycle. For example, when the activity is paused, so are all fragments in it, and when the activity is destroyed, so are all fragments. However, while an activity is running (it is in the resumed lifecycle state), you can manipulate each fragment independently, such as add or remove them. When you perform such a fragment transaction, you can also add it to a back stack that's managed by the activity—each back stack entry in the activity is a record of the fragment transaction that occurred. The back stack allows the user to reverse a fragment transaction (navigate backwards), by pressing the Back button."

Using tabs inside a Fragment (not FragmentActivity)

I'm currently creating an app in which the main screen is build up out of 2 Fragments.
When the user selects options on the main screen, one part of the screen gets replaced by a new Fragment, all pretty much basic stuff.
Now I'm trying to create a screen with several tabs, which all open a new fragment inside them. I had this working with regular intents, but that was before switching to Fragments.
I read that this is possible by using a FragmentActivity, but sadly you can't replace a Fragment with a FragmentActivity, simply because the transaction won't let you.
Is there any way of doing this inside an ordinary Fragment? Or should I try mimicking the behavior by using a layout with a fragment inside which gets replaced by another one at the press of a button, much like the main screen? (Or won't that work due to fragments in fragments?)
There is an example in Android's support library that describes what seems to be what you need. You can find it here: FragmentTabs.

Categories

Resources