Testing Gradle Plugin That Uses project.gradle.projectsEvaluated - unit-testing

I am trying to test a Gradle plugin that uses the BuildAdapter#ProjectsEvaluated function to allow custom configurations and dependencies to be added to my project. The problem that I'm having is that if I evaluate the project using InternalProject#evaluate in the junit test then the projectsEvaluated function is never called. If I switch to the more robust GradleRunner then I do not appear to have the ability to inspect the project(s) later to actually see if my plugin works. I have provided sample code below that shows a sample plugin and a junit test. Does anyone know how I could test this functionality?
class MyPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.extensions.create("myPlugin", MyPluginExtension)
project.gradle.projectsEvaluated {
/*
custom logic that needs to evaluate prior
to gradle adding dependencies to project
*/
}
}
The JUnit is provided below:
class MyPluginPluginTest {
private Project project
#Before
void setup() {
project = ProjectBuilder.builder().build()
project.repositories.mavenCentral()
project.apply plugin: 'java'
project.apply plugin: MyPlugin
}
/*
Test to check whether or not the correct dependency
was added to the project when the plugin was evaluated
*/
#Test
void projectHasCheckerFrameworkDependencies() {
((ProjectInternal) project).evaluate()
Set<File> files = project.configurations.getByName('myPlugin').resolve()
assertNotEquals(0, files.size())
assertTrue(files.any { it.name.endsWith("myDependency-${project.jarName.version}.jar") })
}
}

In order to gain access to the information I required I added the projectsEvaluated closure to the projectExtensions as follows:
class MyPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.extensions.create("myPlugin", MyPluginExtension)
def projectsEvaluatedClosure = {
/*
custom logic that needs to evaluate prior
to gradle adding dependencies to project
*/
}
project.extensions.add("myPluginProjectsEvaluatedClosure", projectsEvaluatedClosure)
project.gradle.projectsEvaluated closure
}
}
Now that the projectsEvaluated closure is accessible in the project I executed the closure manually from the test case. This isn't an ideal solution, but I was able to verify that the code was working properly.

Related

KMM-MockK: Cannot mock the expect object class when I write the unit test case

As the title says, currently I'm having issues using mockk when writing unit tests in commonTest in my KMM project.
In my shared module, I created a useCase class that uses the expected object class to do things like read and write files. But when I follow the guide book(https://notwoods.github.io/mockk-guidebook/docs/mocking/static/) to mock the read and write operations, according to the debug result, it does not seem to excute the result of my mock instead of excuting the real operation.
The part of the use case class:
class UseCase {
fun needToTest{
...
if(FileOperation.mvFile(scr,dest)){
...
}
...
}
}
The example file operation class:
expect object FileOperation {
fun rdFile(path: String): List<Path>?
fun mvFile(srcPath: String, destPath: String): Boolean?
....
}
android Part
actual object FileOperation {
......
actual fun mvFile(srcPath:String, destPath: String): Boolean? {
......
}
.......
}
ios part
actual object FileOperation {
.......
.......
}
The example mockk method what I used currently
val useCaseTest = mock<UseCase>()
mockkObject(FileOperation)
every{ FileOperation.mvFile(srcPathMock, any())} returns true
when{
useCaseTest.needToTest()
}
The dependency in the build.gradle of shared module:
implementation("io.mockk:mockk-common:1.12.2")
You can separate the dependencis of MockK.
I have used this for commonTest:
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation("io.insert-koin:koin-test:$koinVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4")
implementation("io.mockk:mockk-common:1.12.1") //<== THIS FOR MOCKK
}
}
And this one for androidTest:
val androidTest by getting {
dependencies {
// without this, it cannot find "every", "any" and some other functions
implementation("io.mockk:mockk-jvm:1.13.2")
}
}
When you run the tests from Android Studio and JVM you are ready to go, but you need more stuff to be added to run them for iOS. Unfortunately, I have no solution for iOS at the time of this writing.
You can find this solution in my sample project.

Can not run Unitests with Xamarin

I want to check my Xamarin project code (Cookbook) with unit tests. I've created a Unitest for Xamarin project from Visual Studio (UITest1). When I try to run it the linker writes the following error:
Error NU1201 Project Cookbook is not compatible with net461 (.NETFramework,Version=v4.6.1) / win-x64. Project Cookbook supports: monoandroid81 (MonoAndroid,Version=v8.1) UITest1
What am i doing wrong? Tried to Google but with no luck.
This is the Uinitests code if it helps:
using System;
using System.IO;
using System.Linq;
using Cookbook;
using NUnit.Framework;
using Xamarin.UITest;
using Xamarin.UITest.Queries;
namespace UITest1
{
[TestFixture(Platform.Android)]
[TestFixture(Platform.iOS)]
public class Tests
{
IApp app;
Platform platform;
private Ingredient ingr;
public Tests(Platform platform)
{
this.platform = platform;
}
[SetUp]
public void BeforeEachTest()
{
//app = AppInitializer.StartApp(platform);
ingr = new Ingredient();
}
[Test]
public void WelcomeTextIsDisplayed()
{
AppResult[] results = app.WaitForElement(c => c.Marked("Welcome to Xamarin.Forms!"));
app.Screenshot("Welcome screen.");
Assert.IsTrue(results.Any());
}
[Test]
public void ParseFromString()
{
Ingredient ingr = new Ingredient();
ingr.TryToParseFromString("Ingredients");
Assert.AreEqual(0, ingr.Amount, "amount problem");
Assert.AreEqual(null, ingr.Item, "item problem");
Assert.AreEqual(null, ingr.Units, "units problem");
Assert.AreEqual("Ingredients", ingr.Unparsed, "unparsed problem");
}
I see that you're mixing up the concept of unit tests and UI tests since you have both in your test project. What you should do is create two separate projects, for example Cookbook.UITests and Cookbook.UnitTests. The reason is that UI Tests are meant to emulate user behavior while being run on an emulator, real device or perhaps a cloud testing service. Unit tests, on the other hand, should test stuff like the business logic of your code application (to put it simply).
What I would suggest you to do is the following:
Create the two separate projects Cookbook.UITests and Cookbook.UnitTests
Follow the great guidance by SushiHangover on how to set up the unit test project.
Follow the official documentation by Microsoft to set up the UITest project.

Visual Studio 2013: Creating ordered tests

Can someone suggest a way to run tests in a specific order in Visual Studio 2013 Express?
Is there a way to create a playlist for the tests, which also defines the order in which to run them?
By the way: These are functional tests, using Selenium, written as unit tests in C#/Visual Studio. Not actual unit tests. Sometimes a regression test suite is so big it takes a while to run through all the tests. In these cases, I've often seen the need to run the test in a prioritized order. Or, there can be cases where it's difficult to run some tests without some other tests having been run before. In this regard, it's a bit more complicated than straight unit tests (which is the reason why it's normally done by test professionals, while unit tests are done by developers).
I've organised the tests in classes with related test methods. Ex.: All login tests are in a class called LoginTests, etc.
Class LoginTests:
- AdminCanLogin (...)
- UserCanLogin (...)
- IncorrectLoginFails (...)
- ...
CreatePostTests
- CanCreateEmptyPost (...)
- CanCreateBasicPost (...)
...
These classes are unit test classes, in their own project. They in turn calls classes and methods in a class library that uses Selenium.
MS suggests creating an "Ordered Unit Test" project. However, this is not available in the Express edition.
To address your playlist request directly see MS article: http://msdn.microsoft.com/en-us/library/hh270865.aspx Resharper also has a nice test play list tool as well.
Here is an article on how to setup Ordered Tests but you cannot use this feature with Express as it requires Visual Studio Ultimate, Visual Studio Premium, Visual Studio Test Professional. http://msdn.microsoft.com/en-us/library/ms182631.aspx
If you need them ordered then they are more then likely integration tests. I am assuming you would like them ordered so you can either prepare data for the test or tear data back down after the test.
There are several ways to accommodate this requirement if it is the case. Using MSTest there are 4 attributes for this you can see more details of when they are executed here http://blogs.msdn.com/b/nnaderi/archive/2007/02/17/explaining-execution-order.aspx.
My other suggestion would be to have a helper class to preform the tasks(not tests) you are looking to have done in order, to be clear this class would not be a test class just a normal class with common functionality that would be called from within your tests.
If you need a test to create a product so another test can use that product and test that it can be added to a shopping cart then I would create a "SetupProduct" method that would do this for you as I am sure you would be testing various things that would require a product. This would prevent you from having test dependencies.
With that said, integration tests are good to verify end to end processes but where possible and applicable it might be easier to mock some or all dependencies such as your repositories. I use the Moq framework and find it really easy to work with.
This code is from the blog post linked above, I am placing it here in case the link ever dies.
Here is an example of a test class using the setup / tear down attributes to help with your tests.
[TestClass]
public class VSTSClass1
{
private TestContext testContextInstance;
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
[ClassInitialize]
public static void ClassSetup(TestContext a)
{
Console.WriteLine("Class Setup");
}
[TestInitialize]
public void TestInit()
{
Console.WriteLine("Test Init");
}
[TestMethod]
public void Test1()
{
Console.WriteLine("Test1");
}
[TestMethod]
public void Test2()
{
Console.WriteLine("Test2");
}
[TestMethod]
public void Test3()
{
Console.WriteLine("Test3");
}
[TestCleanup]
public void TestCleanUp()
{
Console.WriteLine("TestCleanUp");
}
[ClassCleanup]
public static void ClassCleanUp()
{
Console.WriteLine("ClassCleanUp");
}
}
Here is the order that the methods were fired.
Class Setup
Test Init
Test1
TestCleanUp
Test Init
Test2
TestCleanUp
Test Init
Test3
TestCleanUp
ClassCleanUp
If you give more information on what you are trying to accomplish I would be happy to assist you in when to use which attribute or when to use the help class, note the helper class is NOT a test class just a standard class that has methods you can utilize to do common tasks that may be needed for multiple tests.

Visual Studio 2012 auto create unit test - WP8 application

So, I was also surprised that the "create unit test" is not available from the context menu when right clicking over a method, as opposed to Visual Studio 2010.
The work arounds suggested was to create the unit tests in VS2010 and then import it back to VS2012.
Then i found this post http://dl.my/2013/enable-create-unit-tests-on-visual-studio-2012/
and that indeed worked!
But now, after i click the "create unit test" over a method, the generated class only contains a TestContext property, without the test methods that was chosed in the wizard previously.
This is the generated class:
/// <summary>
///This is a test class for XXXTest and is intended
///to contain all XXXTest Unit Tests
///</summary>
[TestClass()]
public class XXXTest
{
private TestContext testContextInstance;
/// <summary>
///Gets or sets the test context which provides
///information about and functionality for the current test run.
///</summary>
public TestContext TestContext
{
get
{
return testContextInstance;
}
set
{
testContextInstance = value;
}
}
#region Additional test attributes
//
//You can use the following additional attributes as you write your tests:
//
//Use ClassInitialize to run code before running the first test in the class
//[ClassInitialize()]
//public static void MyClassInitialize(TestContext testContext)
//{
//}
//
//Use ClassCleanup to run code after all tests in a class have run
//[ClassCleanup()]
//public static void MyClassCleanup()
//{
//}
//
//Use TestInitialize to run code before running each test
//[TestInitialize()]
//public void MyTestInitialize()
//{
//}
//
//Use TestCleanup to run code after each test has run
//[TestCleanup()]
//public void MyTestCleanup()
//{
//}
//
#endregion
}
I have searched the web with no results..
Does anybody know what's the issue here?
Apparently, it is not possible to use "Generate Unit Tests..." wizard for Windows Phone projects.
As you try to use the wizard, the following error will be prompted:
While trying to generate your tests, the following errors occurred:
You can only add WinMD references to a project targeting Windows 8.0 or higher. To learn how to retarget your project to a different version of Windows, please see the 'Core subgroup' section underneath the 'Windows tab' section in the 'How to: add or remove references by using the Reference Manager' help page: http://msdn.microsoft.com/library/hh708954(v=vs.110).aspx.
The best you can do now is by creating it manually.

How to tell PEX to use the mock object when the concrete object is a dependency, and then auto-generate test cases?

I am writing client-side components in a provided framework, and need to be able to unit test my components. The components are written using MVP (Model-View-Presenter) pattern, I want to use PEX to automatically generate unit tests for my presenters.
The following is the code of a presenter.
public partial class CompetitorPresenter : PresenterBase
{
private readonly ICompetitorView _view;
public IGlobalDataAccess GlobalDataAccess;
public IGlobalUI Globals;
public SystemClient Client;
public bool DeleteRecord()
{
if (_view.CompetitorName != "Daniel")
return false;
if (Client.SystemName != "Ruby")
return false;
return true;
}
}
The problem I am having is that the object SystemClient is provided by the framework, and I cannot use a factory class to create an instance of SystemClient. Therefore when I run PEX to automatically generate unit tests, I have to tell PEX to ignore SystemClient, the result of this is that the method DeleteRecord is not fully covered as the line Client.SystemName != "Ruby" is not tested.
Since I have the mock object MSystemClient (created using moles), I am wondering if somewhere in the configuration I could tell PEX to use MSystemClient, and let PEX to automatically generate test cases to fully cover this method.
You are on the right track. If you cannot control where the instance of CompetitorPresenter.Client is created, you can define a mole for all instances:
MSystemClient.AllInstances.SystemNameGet = () => "SomeName";
Your unit test has to be run in a "hosted environment":
[HostType("Moles")]
public void TestMethod()
{
MSystemClient.AllInstances.SystemNameGet = () => "SomeName";
// Test code...
}