How to pass data from one test to another in Xunit? - c#

I am using Playwright with C# and Xunit, but I think Selenium and Xunit users can help as well.
I need to get the value of an element in one test and pass this value to another test.
For example,
[Fact]
public async Task GetData()
{
var data = await Page.GetAttribute(selector1, "value");
}
[Fact]
public async Task PassData()
{
await Page.FillAsync(selector2, data);
}
This is a simple example, the real-life test has a lot of steps, so I want to break one big into several small tests.

Related

How can I pass parameters in a [Setup] or [OneTimeSetup] so I so not have call the method in my test class?

In TestNg We have #BeforeMethod where we can pass parameters.
But in Nunit I get this exception "OneTimeSetUp: SetUp and TearDown methods must not have parameters: TestInitialize" I am trying to Create the extent report for each test in the class with out calling .CreateTest method in every [Test] method
[SetUp]
public void TestInitialize(MethodInfo method)
{
StartReport(TestContext.CurrentContext.Test.Name);
string testName = method.Name;
test = extent.CreateTest(testName);
}
[Test]
public void GetHealthTest()
{
test.Log(Status.Info, "Before calling GetHealth API");
var health = heartbeat.GetHealth();
test.Log(Status.Info, "After GetHealth API call");
Assert.AreEqual(health.StatusCode, HttpStatusCode.OK);
}
If all you want is the name of the current test in your SetUp, use TestContext.CurrentContext.Test.Name. There are other properties, like FullName and MethodName as well, depending on what you prefer to see in your report.
That said, even with use of SetUp, this is a very "busy" way to do reporting. NUnit also supports engine extensions, which allow you to create reports outside of the test assembly itself. In addition, it's possible to simply write a program that reads the XML result file from a test run and creates a report.

How do I verify if something didn't happen?

We are using OpenCover for our solution test coverage and I noticed that
public async Task Build(ProcessorContext context)
{
context.ResultBetSlip.Bets.Clear();
// Here OpenCover tells me that I need to cover two branches
// so I assume I need to verify that GetAvailablePlugins can be empty and
// no Build method was called.
// How do I do that?
foreach (var plugin in _pluginFactory.GetAvailablePlugins())
{
await plugin.Build(context);
}
}
Now my test would look like that
[Test]
public async Task Build_ShouldntEnterForeachWhenThereAreNoPluginsRegistered()
{
// Arrange
var pluginFactoryMock = new Mock<IBetSlipProcessorServicePluginFactory>();
var sut = new BetSlipProcessorService(pluginFactoryMock.Object);
pluginFactoryMock
.Setup(pf => pf.GetAvailablePlugins())
.Returns(new List<IBetSlipProcessorServicePlugin>());
// Act
await sut.Build(AutoFixtureSimplified.Create<ProcessorContext>());
// Assert
???
}
Should I even consider testing such case if it is possible?
EDIT:
As requested this is the test coverage report:
And here you can find gist of all the tests that I do in order to achieve such coverage.
https://gist.github.com/kuskmen/df3f112b2b6d880741ee6ab559d64d53
I am assuming you are using the Moq framework for mocking. If this is the case you can do one of two things.
You can create your mock in strict mode
You can expect that when the plugin.Build(..) method is called that an exception is thrown.
A similar question was asked here: How to verify that method was NOT called in Moq?
edit:
I simulated the exact scenario that you are seeing and I have narrowed it down to the data type that you are iterating over. Due to the fact that you are using a list I would guess there is some internal workings of the list that are causing this problem. I changed all the list references to arrays and the branch coverage returned as expected.

NUnit async tests fail after merge

NUnit 2.6.4.
I have a VS/C# project that introduces async methods. It has many tests like this that pass:
[Test]
public async void NullProcThrows_Async()
{
var keyList = new KeyList<int>();
Assert.Throws<ArgumentNullException>(async () => await keyList.LoadAsync((IDBProcedure)null, "ID", CancellationToken.None));
}
I have merged this into our trunk (no conflicts) and now this test fails. I am trying to figure out the difference.
When I trace the code in the trunk I see two exceptions thrown:
The first is the ArgumentNullException I am expecting.
The second is
NUnit.Framework.AssertionException saying Expected
<System.ArgumentNullException> But was: null
When I run the test on the branch version I only see the one exception and the test passes.
What could be different between the two projects?
There seems to be a few issues with the code provided, consider the following:
[Test, ExpectedException(typeof(ArgumentNullException)]
public async Task NullProcThrows_Async()
{
var keyList = new KeyList<int>();
await keyList.LoadAsync((IDBProcedure)null, "ID", CancellationToken.None);
Assert.Fail("This should never be executed as we expected the above to throw.");
}
According to the NUnit documentation, you should be using the ExpectedException attribute instead of Assert.Throws. So I added that attribute and then remove the Assert.Throws and instead add Assert.Fail. Also, I made the method Task returning and this prevented the async void. Finally, doing it this way prevents the async lambda.

xUnit not awaiting async test

On VS 2013, I can't get this async test to fail.
I have xUnit 1.8.0.1539 (installed from nuget), with the xUnit Test Runner VS extension (0.99.5). All current, AFAIK.
I happen to also have Moq, AutoFixture, and FluentAssertions reference in the unit test, but I don't think that matters (but I'm admitting it in case it does).
I have done async unit tests in other areas of my solution, and they work.
I'm missing something with this newly created tests, and I can't tell what I'm missing or doing wrong.
NOTE The SUT code is not meant to be complete. I'm just trying to get the red light first, before I write the code to make the test go green.
Here's the test code:
using System.Threading.Tasks;
using FluentAssertions;
using Xunit;
namespace MobileApp.Proxy.Test
{
public class WhenRetrievingPriceDataFromClient
{
[Fact]
public async Task GroupReportIsReturnedWithSomeData()
{
// arrange
var sut = new Client();
// act
var actual = await sut.GetReportGroupAsync();
// assert
// Xunit test
Assert.Null(actual);
Assert.NotNull(actual);
// FluentAssertions
actual.Should().BeNull();
actual.Should().NotBeNull();
}
}
}
And here is the SUT code:
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Threading.Tasks;
using MobileApp.Proxy.Properties;
namespace MobileApp.Proxy
{
public class Client
{
public async Task<ReportGroup> GetReportGroupAsync()
{
return await Task.FromResult(new ReportGroup());
}
}
}
Obviously, this test should fail! The Asserts for Null and NotNull can't both succeed, so my conclusion is that the test is exiting before it finishes getting the response from the SUT.
What did I miss?
OR, is there a better way I should have started an async test to make sure it fails before writing the SUT code?
You need xUnit 1.9 for async unit tests to work correctly.
Async tests are supported in xUnit v1.9 or later. If you're stuck with an earlier version, you'll need to do something like this:
[Fact]
public void GroupReportIsReturnedWithSomeData()
{
GroupReportIsReturnedWithSomeDataAsync().Wait();
}
private async Task GroupReportIsReturnedWithSomeDataAsync()
{
// arrange
var sut = new Client();
// act
var actual = await sut.GetReportGroupAsync();
// assert
// Xunit test
Assert.Null(actual);
Assert.NotNull(actual);
// FluentAssertions
actual.Should().BeNull();
actual.Should().NotBeNull();
}
Basically, the test method blocks until the async test method completes, whether it'd due to successful completion or fault (e.g., a failed assertion). In the case of a fault, the exceptions will propagate to the main test thread through Wait().
You may want to pass a timeout to Wait() so your test will fail if it hasn't completed after a certain amount of time. As written, the test could block indefinitely if the async method never completes.

Holding a Value in Unit tests

I have a Question for you guys.I have 2 unit tests which are calling webservices .The value that one unit-test returns should be used for another unit test method
Example
namespace TestProject1
{
public class UnitTest1
{
String TID = string.empty;
public void test1
{
//calling webservices and code
Assert.AreNotEqual(HoID, hID);
TID = hID;
}
public void test2
{
//calling webservices and code
string HID = TID // I need the TID value from the Above testcase here
Assert.AreNotEqual(HID, hID);
}
}
}
How can i store a value in one unittest and use that value in another unittest.
In general, you shouldn't write your tests like this. You cannot ensure that your tests will run in any particular order, so there's no nice way to do this.
Instead make the tests independent, but refactor the common part into it's own (non-test) method that you can call as part of your other test.
Don't reuse any values. Order in which tests are run is very often random (most common runners like NUnit's and Resharper's run tests in random order, some might even do so in parallel). Instead, simply call web service again (even if that means having 2 web service calls) in your second test and retrieve the value you need.
Each test (whether it's unit or integration) should have all the data/dependencies available for it to run. You should never rely on other tests to setup environment/data as that's not what they're written for.
Think of your tests in isolation - each single test is a separate being, that sets up, executes, and cleans up all that is necessary to exercise particular scenario.
Here's an example, following the outlines of Oleksi, of how you could organize this
String TID = string.empty;
[TestFixtureSetUp]
public void Given() {
//calling webservices and code
TID = hID;
//calling webservices and code
}
[Test]
public void assertions_call_1() {
...
}
public void assertions_on_call_2() {
if (string.IsNullOrEmpty(TID))
Assert.Inconclusive("Prerequisites for test not met");
...
}

Categories

Resources