Run Xunit and UI Tests test from code with reflection - c#

I am trying to run CodedUI Tests from MTM as well as running Xunit tests on our code base. I am supposed to be able per my requirements to run these tests from ONE project so as to be able to gather data on the tests later on. I have been able to get the tests to run in both instances from the same code using reflection to call test methods based on their respective attributes.
The problem is, then for both the UI and the Xunit tests, the Test Explorer is not registering that the tests are passing or failing. I assume that there is some initialization that must occur for the testing environment, but I can't find any resource on it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CodedUITestProject1;
using Microsoft.VisualStudio.TestTools.UITesting;
using CodedUITestProject2;
using System.Reflection;
using ConsoleApplication1;
namespace Run_UI_From_Outside
{
class Program
{
static void Main(string[] args)
{
// This section uses reflection to find Test Methods in the CodedUITest class bases on their attributes
var assembly = typeof(CodedUITestProject2.CodedUITest1).Assembly;
var attributes = assembly.GetCustomAttributes(typeof(CodedUITestProject2.CodedUITest1), true);
var types = assembly.GetTypes();
foreach (var t in types)
{
var ca = t.CustomAttributes;
foreach (var item in ca)
{
if (item.AttributeType == typeof(Microsoft.VisualStudio.TestTools.UITesting.CodedUITestAttribute))
{
object myInstance = Activator.CreateInstance(t);
MethodInfo myInstanceMethod = t.GetMethod("CodedUITestMethod1");
Playback.Initialize();
var test = myInstanceMethod.Invoke(myInstance, null);
Playback.Cleanup();
}
}
}
// This section uses reflection to find Xunit Methods in the CodedUITest class bases on their attributes
var assemblyXunit = typeof(ConsoleApplication1.Tests.SampleTest).Assembly;
var xunitMethods = assemblyXunit.GetTypes().SelectMany(t => t.GetMethods())
.Where(a => a.GetCustomAttributes(typeof(Xunit.FactAttribute), false).Length > 0)
.ToArray();
foreach (var t in xunitMethods)
{
object myMethodInstance = Activator.CreateInstance(t.DeclaringType);
t.Invoke(myMethodInstance, null);
}
}
}
}

Related

How to unit test SourceGenerator?

I writed a SourceGenerator, but how do I test it?
Main issue is how to imitate GeneratorExecutionContext (or just Compilation inside it) which generator gets into Execute method. I think there is a proper way to make fake SyntaxTrees for unit testing, but I cant find it. There are many articles about source generators itself, but none of them explain how to test generators.
You should look at official Source Generators Cookbook
There is example from it:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
namespace GeneratorTests.Tests
{
[TestClass]
public class GeneratorTests
{
[TestMethod]
public void SimpleGeneratorTest()
{
// Create the 'input' compilation that the generator will act on
Compilation inputCompilation = CreateCompilation(#"
namespace MyCode
{
public class Program
{
public static void Main(string[] args)
{
}
}
}
");
// directly create an instance of the generator
// (Note: in the compiler this is loaded from an assembly, and created via reflection at runtime)
CustomGenerator generator = new CustomGenerator();
// Create the driver that will control the generation, passing in our generator
GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);
// Run the generation pass
// (Note: the generator driver itself is immutable, and all calls return an updated version of the driver that you should use for subsequent calls)
driver = driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out var outputCompilation, out var diagnostics);
// We can now assert things about the resulting compilation:
Debug.Assert(diagnostics.IsEmpty); // there were no diagnostics created by the generators
Debug.Assert(outputCompilation.SyntaxTrees.Count() == 2); // we have two syntax trees, the original 'user' provided one, and the one added by the generator
Debug.Assert(outputCompilation.GetDiagnostics().IsEmpty); // verify the compilation with the added source has no diagnostics
// Or we can look at the results directly:
GeneratorDriverRunResult runResult = driver.GetRunResult();
// The runResult contains the combined results of all generators passed to the driver
Debug.Assert(runResult.GeneratedTrees.Length == 1);
Debug.Assert(runResult.Diagnostics.IsEmpty);
// Or you can access the individual results on a by-generator basis
GeneratorRunResult generatorResult = runResult.Results[0];
Debug.Assert(generatorResult.Generator == generator);
Debug.Assert(generatorResult.Diagnostics.IsEmpty);
Debug.Assert(generatorResult.GeneratedSources.Length == 1);
Debug.Assert(generatorResult.Exception is null);
}
private static Compilation CreateCompilation(string source)
=> CSharpCompilation.Create("compilation",
new[] { CSharpSyntaxTree.ParseText(source) },
new[] { MetadataReference.CreateFromFile(typeof(Binder).GetTypeInfo().Assembly.Location) },
new CSharpCompilationOptions(OutputKind.ConsoleApplication));
}
}
In addition to the Source Generators Cookbook mentioned in the other answer:
The cookbook solution allows you to generate some code and then compare your results to expected, also check for warnings and compilation exceptions etc.
Now, you can additionally EXECUTE the generated code to make sure it's running correctly. For that change the project reference in the test-project like this:
<ProjectReference Include="..\MyGenerator\MyGenerator.csproj"
ReferenceOutputAssembly="true"
OutputItemType="Analyzer" />
And then simply call the generated code from your unit tests, like you would in the consumer project.

C# TestProject - How do I get CodeFilePath & LineNumber for each test?

Given:
I have a project/solution containing tests. It is written in C# and is using nUnit.
What I want:
Somehow to retrieve all the tests in the Project/Solution without executing them and also giving me the CodeFilePath and LineNumber for each test.
What I tried / investigated:
dotnet test --list-tests : is giving me nothing (just the displayname)
NUnit3TestAdapter : is at somepoint exposing those values (see NUnitTestAdapter).
But how can I retrieve them?
Thanks #Charlie for pointing out a possible solution. I did basically exactly as you stated.
IMPORTANT NOTICE:
This seems to not work with dot.net CORE tests currently because of this issue: https://github.com/nunit/nunit-console/issues/710
Also DiaSession runs into an exception when used like this in dot.net CORE :-(
using System;
using System.Xml;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using NUnit.Engine;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var testAssemblyPath = #"C:\src\qata\src\tests\external\SomethingProject.Tests\bin\Debug\net461\SomethingProject.Tests.dll";
var package = new TestPackage(testAssemblyPath);
var testEngine = new TestEngine();
var runner = testEngine.GetRunner(package);
var nUnitXml = runner.Explore(TestFilter.Empty);
var session = new DiaSession(testAssemblyPath);
foreach (XmlNode testNode in nUnitXml.SelectNodes("//test-case"))
{
var testName = testNode.Attributes["fullname"]?.Value;
var className = testNode.Attributes["classname"]?.Value;
var methodName = testNode.Attributes["methodname"]?.Value;
var navigationData = session.GetNavigationData(className, methodName);
Console.WriteLine($"{testName} - {navigationData.FileName} - {navigationData.MinLineNumber}.");
}
}
}
}

MessagingCenter callback fails to register

I'm making an app with xamarin.forms and I have an issue with unit testing part. The problem is that when the test case runs isolated it passes, but when I run all the tests it fails.
using EmpresaPersonal.Modelos;
using EmpresaPersonal.ModelosVisuales;
using EmpresaPersonal.Services;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xunit;
namespace EmpresaPersonal.Test
{
public class PruebasVMEditarContacto
{
[Fact]
public async Task GuardarContactoSeteaCorrectamenteAsync()
{
// Preparamos el editor y los eventos
var store = new MockDataStore();
var mockNavegacion = ServiciosFalsos.MockIrAtras();
var editor = new MVEditarContacto(store, mockNavegacion.Object)
{
// Initializer setters...
};
bool llamado = false;
MessagingCenter.Subscribe<MVEditarContacto, string>(this, MVEditarContacto.EventoContactoCreado, async (s, idContacto) => // This line throws a NullReferenceException
{
var contacto = await store.GetItemAsync(idContacto);
// Algunos chequeos van por acá
Assert.NotNull(contacto);
Assert.Equal(editor.Nombre.Valor, contacto.Nombre);
Assert.Equal(editor.Empresa.Valor, contacto.Empresa);
Assert.Equal(editor.TelefonoPrincipal.Valor, contacto.TelefonoPrincipal);
Assert.Equal(editor.TelefonoSecundario.Valor, contacto.TelefonoSecundario);
llamado = true;
});
editor.GuardarContacto.Execute(null);
await editor.EsperarCompletarAsync();
Assert.True(llamado, "El evento no fue llamado.");
mockNavegacion.Verify(m => m.AtrasAsync());
}
}
}
I don't use anything than MessagingCenter.Send` from the model instantiated in this chunk. I have to say that I have another test for a model that subscribes to this model, to the same event in it's constructor (the model is the subscriber).
Any ideas?
I saw that when unit testing very xamarin.forms related code such MessagingCenter, the best way is to run the tests from Xunit.Runner.Devices test runner (A.C.A. with a real and initialized xamarin.forms environment).
The best example I've found is the EShop on containers mobile app.
I've just left my project and started a new one heavily based on Prism.Forms to ease unit testing these kind of things because it is constructed on top of IOC containers.

How can I roll back changes with Entity Framework 5 within a Unit Test project

I'm playing with Entity Framework, and I have a Unit Test project that I want to exercise what I've done so far. I'd like to have it not actually update my test database when it's done. If I was working in SQL I would create a transaction and then roll it back at the end.
How can I do the same thing here?
As I understand it, context.SaveChanges(); is effectively doing the write to the database. And if I don't have that, then allCartTypes is empty after I assign it context.CarTypes.ToList()
Here's an example of one of my Test classes.
using System;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Trains;
using System.Linq;
namespace TrainsTest
{
[TestClass]
public class TestCarType : TestBase
{
[TestMethod]
public void TestCarTypeCreate_Success()
{
var tankerCarType = new CarType {Name = "Tanker"};
var boxCarType = new CarType { Name = "Box" };
using (var context = new TrainEntities())
{
context.CarTypes.Add(tankerCarType);
context.CarTypes.Add(boxCarType);
context.SaveChanges();
var allCartTypes = context.CarTypes.ToList();
foreach (var cartType in allCartTypes)
{
Debug.WriteLine(cartType.CarTypeId + " - " + cartType.Name);
}
}
}
}
}
I know I'm missing something fundamental, but I don't know what it is. and my googling has been fruitless.
There's a MSDN article about ef transactions.
http://msdn.microsoft.com/en-gb/library/vstudio/bb738523(v=vs.100).aspx

c# unit testing visual studio 2010

I'm new to c# and programming in general. Need to write some unit testing. Want to write some for this class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using teamcanada.Models;
using System.Configuration;
using teamcanada.ingestion;
/* This class writes the parsed CSV data into the database */
namespace teamcanada.dal
{
public class csvParseDAL
{
protected torontoDB db = new torontoDB();
/* if the database is empty, then do not continue with the CSV parsing */
public csvParseDAL()
{
if ((db.ElectionResults.ToList().Count() == 0) && (db.ElectionContributions.ToList().Count() == 0))
{
insertcsv();
}
}
/* Start CSV parsing */
public void insertcsv()
{
List<Results> results = null;
List<Contributions> contributions = null;
LoadCSV import = new LoadCSV();
results = import.loadResults();
foreach (Results r in results)
{
db.ElectionResults.Add(r);
}
contributions = import.loadContributions();
foreach (Contributions r in contributions)
{
db.ElectionContributions.Add(r);
}
db.SaveChanges();
}
}
}
Any help is appreciated.
D
Generally what you'll want to do is to use the Assert class to compare expected and actual values. The actual values are usually return values of methods. In your case, I would recommend testing the return values of import.loadResults(); and import.loadContributions(); to make sure they return what you expect.
I see you use EF which is not something you need to unit test, that has already been done by Microsoft. If you need to you can use integration tests, where the tests have access to the database and check whether proper values have been inserted.
It is hard to give more specific advice, just create a Test Project in Visual Studio, play a round a bit and than maybe try asking more specific questions. You can use this presentation to understanding the basics of unit testing.

Categories

Resources