Queries on Unit Testing in Xamarin - xamarin

I'm developing cross platform app for Android, Windows Desktop 8.1, WinPhone 8.1, iOS on Xamarin and now added Test projects. I went through multiple resources for UITests but had following queries. It could be helpful if anyone can correct me.
Projects of type Android test, Windows Phone test, iOS test exists. When these are run, these executes as an app in device/emulator. So, how would these test original app running on same device?
If I have two different android project, how can I specify in above test projects which one to test?
I also added UITest project, which is class library project. In this I can mention apk file using following code:
[SetUp]
public void BeforeEachTest()
{
app = ConfigureApp.Android.ApkFile(#"Path\to\apk\com.namespace.apk")
.DeviceSerial("emulator-1234")
.StartApp();
}
How to reference a project to test rather then .apk file, so I could modify project every time I run tests?
How can I combine UITest project and native test projects? Like common portable library is referenced by native projects.
Thanks in advance

Regarding point 4.
At present, running console UnitTests against Xamarin.Forms, i.e testing the ViewModel, Commands, and Navigation in isolation of the UI takes a fair bit of setup. Testing the ViewModels in total isolation of the Xamarin.Forms framework disallows testing across multiple ViewModels.
For instance, testing a login viewmodel in complete isolation where:
user enters username/password
click login button
redirected to the authenticated screen with their data populated
will not work, as that requires a hook on the viewmodel navigation, so the test can authenticate on the Login ViewModel, then navigate and initialise the Authenticated ViewModel.
So I put out a nuget library that allows to simply achieve this, and also provide Bdd using specflow. The test run as nunit test on vs test shell, or any nunit console runners (such as in Build Servers such as Team City).
Example:
public class GeneralSteps : TestStepBase
{
public GeneralSteps(ScenarioContext scenarioContext)
: base(scenarioContext)
{
// you need to instantiate your steps by passing the scenarioContext to the base
}
[Given(#"I am on the main view")]
public void GivenIAmOnTheMainView()
{
Resolver.Instance.Resolve<INavigationService>().PushAsync<MainViewMode>();
Resolver.Instance.Resolve<INavigationService>().CurrentViewModelType.ShouldEqualType<MainViewModel>();
}
[When(#"I click on the button")]
public void WhenIClickOnTheButton()
{
GetCurrentViewModel<MainViewModel>().GetTextCommand.Execute(null);
}
[Then(#"I can see a Label with text ""(.*)""")]
public void ThenICanSeeALabelWithText(string text)
{
GetCurrentViewModel<MainViewModel>().Text.ShouldEqual(text);
}
}
Step by step instructions here
Nuget package here

Not sure I understand this question.
UITest will deploy and run the app in the device/emulator and will then run the tests against that app. For iOS apps being tested it will start the emulator for you. For Android apps being tested you will have to start the emulator yourself. If they are different Android apps then presumably the UITests would be different for each Android app so keeping the UITests as separate project seems reasonable, especially if you are uploading the tests to Xamarin Test Cloud.
Also note that UITest does not support Windows Phone projects currently, so it can only be used to test your Android and iOS project.
With two different Android projects you would either create a UITest project for each Android project or you would need to specify the path to the .apk file in the test, using ConfigureApp.Android.ApkFile () as you have already done in the code example.
If you are using Xamarin Studio you can run the UITests directly in the IDE without having to specify the full path to the .apk file or the iOS .app.
What you would need to do is have the UITest project reference the Android project. However it needs a special type of reference so you will need to use Xamarin Studio to do this. You add this special type of reference from the Unit Tests window, by finding the Test Apps item, selecting Add App Project and then selecting the Android and/or iOS project.
More information is available in the Adding UITest to a solution on Xamarin's developer guide.
Note that you can have a single UITest project test both the iOS and Android apps. Assuming that they are both the same application. However you may need to create Android and iOS specific UI test queries to find UI elements on the screen.
First you should ask yourself if you really need to combine UITests with native test projects. For example the UITests may take a long time to run, so if you have some fast unit tests you may not want to run them all together.
Combining them is possible if the native test projects are essentially NUnit projects. A UITest project is basically a NUnit project. It has a reference to NUnit and is a class library. If your native tests can be run from a NUnit project then you could combine them. However you would not be able to run the native tests in Xamarin's Test Cloud.
If the native test projects do not use NUnit then you cannot combine them with the UITest project.

Related

How to add system api classes to your android project for non AOSP builds

I have an android system app that is currently being built with the android build system. The SDK in use is system_current as it uses some system apis.
For external dependency reasons, ease of development, debugging etc, it would be nice to move this app to Android Studio and use Gradle to build.
Converting the sources to build with Gradle is straight forward enough. However, at build time, the system APIs are not found as those are not available in the normal SDK. I thought that by generating the SDK from the AOSP sources I'd get an SDK I could use, but that target output seems to also not have the System APIs available.
How would I change my gradle build to be able to use the System SDK to compile against?
There are two ways depending if you are only trying to use current non-public APIs, or of you've added custom ones yourselves and are trying to access those.
If you're only trying to use current system-level APIs, you can use android.jar from this repository https://github.com/anggrayudi/android-hidden-api
If you have added some new method that isn't part of standard AOSP, then it's a but more work.
The reason that all methods don't show as part of Android SDK is that in AOSP code they are annotated with #hide. This means that when SDK is generated, they are exlcuded.
You'll need to remove that annotation for the methods that you want to use. Then you'l need
Run make update-api to update the public API of the project.
Make the Android SDK from code by following: https://android.googlesource.com/platform/sdk/+/master/docs/howto_build_SDK.txt
Change the Android SDK path in Android Studio to use the custom one you build.
There's also the possibility of accessing methods via reflection on runtime without SDK generation. It's slower and messier to code though.
Not sure I understand exactly what you mean by normal SDK etc.
From https://developer.android.com/studio/build
The key part is to have a
apply plugin: 'com.android.library'
...
android {
...
}
If on the other hand you wanted to build with a desktop JDK but compile against java APIs you could add a dependency on robolectric and you can get a jar you can import into another Android project.
implementation "org.robolectric:android-all:11-robolectric-6757853"
Android Studio isn't really designed to work with System APIs. Even if you make Gradle build your platform app, you will also need to sign it with the same certificate as your AOSP build (so that you could run it). As you noticed, if you decide to use Roboelectric you would also need to modify it yourself to match your current AOSP version (System APIs are not as stable as Public APIs and Roboelectric needs to constantly chase all the changes).
I would suggest to keep using the AOSP build system but optimize our workflow.
Ease of development
Doing a full build/flash for every change in your component must be a pain. But if you are just modifying a single app, you can get away with just building that single component:
~/aosp/ $ m -j -- do a full build first
flash a clean image (with your platform certificate)
~/aosp/path/to/your/app/ $ mma -j -- build your app with all dependencies after you made changes
$ adb root && adb remount && adb sync
Basically, adb sync works great if you don't touch any APIs or parts of Android Framework (which would cause a rebuild of thousands other objects). If you see adb sync updating more than handful of files, you'll likely end up with a bad system and need to do a full flash.
Debugging
While Android Studio is a to-go solution for regular apps, framework and the platform apps go with InteliJ (you can probably use Android Studio, but there won't be much of use of Android plugins on top InteliJ) plus some configuration (see idegen.sh - example).

How to use ServiceCore framework from salesforce in a Xamarin forms app?

I am getting a warning in my console when I try building the app in Release configuration. The warning reads The ServiceSDK frameworks have not been prepared for release.
Please ensure the "prepare-framework" script is run after the "Embed Frameworks" build phase.
From the documentations, I understand that a build phase script has to be run to fix the issue.
Here is how I use the framework in my solution:
I am creating a binding library which refers the framework through a Native Reference. Then I run the library project and build a .dll with I use in the iOS project within my Xamarin forms application. All this is working fine. I am able to use the intended features from the framework.
However, there is this warning which appears in the console when I run the App in Release configuration. Also, when I tried submitting the App to App Store, it throws error, which is apparently the same mentioned above.
I tried by adding Custom commands which I think is the equivalent of Xcode build phase scripts, but the warning doesn't simply go away.
Any help would be really appreciated.
Sample Repos - https://github.com/XamarinUniversity/ENT302
Youtube Video Link - https://www.youtube.com/watch?v=HEypPXVoYnY&feature=youtu.be
Gudie Here - https://xamarinuniversity.github.io/ENT302/

Can I link an XCUITest target to a different Project's app target OR use XCTest/XCUITest outside of a UI Test Bundle target?

I am currently building out a test suite in an Xcode workspace that contains 3 existing projects. 2 App projects and a common framework project. Both apps are very similar in regards to UI with some minor differences.
I am trying to find a way to share the XCUITest framework I made for App A with App B.
Currently, App A has a test target set inside of its AppA.xcodeproj. All of App A's tests are doing great and easy to maintain. I need to extend this to App B and refactor App A's framework to only the App A exclusive bits so App A and App B can share the common XCUITest framework code base from a central base.
I have tried to create a new project, move over the UI test code and point the new UI Test target at App A's executable, but I could not figure out how to get the option to show.
I set the App A app as a Target Dependency in the New Project's test target > Build Phases tab, but no luck. I was able to set App A's target in the new test target's scheme but still landed on an error.
Assertion Failure: CommonBasePage.swift:21: failed: caught "NSInternalInconsistencyException",
"No target application path specified via test configuration: <XCTestConfiguration: 0x60400014e910>
testBundleURL:file:///Users/user.name/Library/Developer/Xcode/DerivedData/.../Debug-iphonesimulator/NewTestTarget-Runner.app/PlugIns/NewTestTarget.xctest/
testBundleRelativePath:(null)
productModuleName:NewTestTarget
testsToSkip:(null)
testsToRun:NewBasePage/testExample
reportResultsToIDE:YES
sessionIdentifier:<>
pathToXcodeReportingSocket:(null)
disablePerformanceMetrics:no
treatMissingBaselinesAsFailures:no
baselineFileURL:(null)
baselineFileRelativePath:(null)
targetApplicationPath:(null)
targetApplicationBundleID:(null)
testApplicationDependencies:
{...
I'm assuming targetApplicationPath:(null), targetApplicationBundleID:(null) should have legit target values but I'm unsure where else to look in order to set them.
I gave up on that and tried to create a new project & target as a Cocoa Touch Framework to shift the common code to a central point but was not able to import XCTest, which my framework depends on for XCUIApplication and XCUIElement fields.
import XCTest //Causes "Cannot load underlying module for 'XCTest'"I tried adding XCTest.framework to the targets "Link Binary with Libraries" section under build phases but no luck.
Is there a way to work with the XCTest framework outside of a test target?
OR
Is there a way to point one project's test target at another project's app target?
You can link XCTest and any other framework to anything. Make sure you have $(PLATFORM_DIR)/Developer/Library/Frameworks in both LD_RUNPATH_SEARCH_PATHS and FRAMEWORK_SEARCH_PATHS.
Making framework for shared code is a good idea.

NSLocalizedRecoverySuggestion=Could not find the requested application

Xamarin.UITest gives an error:
"NSLocalizedRecoverySuggestion=Could not find the requested
application."
I tried with the released app version with the distributable provisioning profile.
Can't we test the release version app using xamarin.uitest?
On iOS, No.
You can not normally use UITest on the iOS release builds as it does not include the UITest agent (it is normally #if/#end out of release configurations).
Test frameworks like UITest/Calabash use a http-based driver that has to be included in the actual app in order to drive it, on the other hand frameworks like Appium use a driver that is external to the application being tested. (Appium directly uses the iOS XCUITest test framework for all iOS testing, Calabash, and UITest, uses a hybrid-approach, XCUITest-based and some custom via the bound HTTP driver)

iOS Unity3D game with Apple Watch companion

guys.
First goes the questions.
I need to combine different Xcode projects for iOS and watchOS. And I need automation for this.
Is it possible to set reference in iOS-Xcode project to watchOS-Xcode project, and setup outer project to build target iOS app with embedded watchOS app, by using targets of inner project? Is it possible to do such a thing with workspaces?
Are there exist some command line tools for managing Xcode project, like adding targets, changing build settings, setup build phases, add resources and so on?
Problem summary.
I'm currently developing video game with Unity3D for iOS and want to make a companion application for watchOS. The problem is that Unity doesn't have any built-in support for watchOS, thus I have to care about integration of watchOS part by myself.
I have Unity project for the game itself and different Xcode project for watchOS part of the game. Now I combine Unity-generated Xcode project with the necessary parts of watchOS project manually: I create WatchKit App target, then import necessary resources from the separate watchOS-project, setup build settings as required - and that do the thing, I get the game with Apple Watch support.
The thing is, that I need to do automation for this process. But I haven't found some useful information on this topic neither here (on stackoverflow), not did on official apple developers' site, not on unityanswers.com, nor in Xcode documentation.
Thanks in advance.

Resources