>> On today's Visual Studio Toolbox,
we're going to continue looking at unit testing
tools and we're going to explain xUnit.
Hi, welcome to Visual Studio Toolbox.
I'm your host, Robert Green.
Joining me is Phil Japikse. Hey, Phil.
>> Hey, Robert.
>> This is part two of
our multipart series on unit testing.
>> It is.
>> We covered an introduction in unit testing
and test-driven development in the previous episode.
Today, we're going to do a deep dive on xUnit.
>> Yeah. We want to make sure that after all this is
Visual Studio Toolbox that we cover
the tools so that you aren't hindered by the tooling.
>> Right.
>> It's mean to say. So, let's summarize xUnit.
>> So what is xUnit?
Give us a little of a history.
Where do you get it?
How do you add it to your project?
>> Sure.
>> Then we'll talk about how to use it.
>> So, there's a couple of ways to add it.
The easiest way is go out to NuGet and search for xUnit.
>> It is a testing framework, basically.
>> It is a testing framework and then
it also has a runner built into it.
Here are the xunit.runner.visualstudio
package enables it to tie into the Visual Studio runner.
>> Okay.
>> That also works with
ReSharper and many other libraries.
If you go out to NuGet,
you can get add in a for team city for VSTS,
for MS build, for everything else,
so you can run it from a build process as well.
>> So, works inside Visual Studio,
works in the Test Explorer.
Does it work with Live Unit Testing?
>> It does work with Live Unit Testing as well.
>> Okay.
>> The other way, real quick, if I say, Add,
New Project, this is how important it is to Microsoft.
I can go.NET Core xUnit test project.NET Core.
So, it sets it up for you.
>> Okay.
>> You'll just want to update
the packages because the template,
of course, as soon as the template ships the entire date.
>> Right.
>> Right. With all templates, so then you would just
right click and say update the NuGet packages.
>> Okay.
>> So, xUnit is what I typically use,
it was one of the first ones to
be compatible with.NET Core.
It's not to say that other testing frameworks are bad,
it's just the one I prefer.
>> Sure.
>> Unit works, MB unit works, MS Test works.
I have some issues with how it works.
>> Fair enough.
>> We're going to cover a couple of those here
early on the differences.
So, we saw a quick demo in the last episode of xUnit.
Again, I want to go into great detail.
There are some name changes
that might throw you for a little bit of a loop,
maybe 30 seconds from NUnit and MB Unit.
>> Okay. So, if you were using NUnit and MB Unit,
things are named differently in xUnit.
If you are new to all of these?
>> Then there is no name change.
>> Right, exactly. All right.
>> But in the prior frameworks,
we would call a test a test,
seems quite simple, and then,
a data-driven or scenario-driven test,
a road test, typically.
It's just a Fact now. That's the name.
It is a fact that it is a Fact.
Yeah, they just changed the name to Fact.
In theory is then a data-driven test.
So, that's something that
might take you 30 seconds to get used to if
you're coming from existing framework
or it's brand new. Hey, you know what?
We are stating that this is
a fact that this assertion is true,
and then we have the theory that all of
these assertions and scenarios will be true.
>> Okay.
>> So, we can also ignore tests.
Now, this is considered an anti-pattern in
the testing world to ignore unit test,
because if you have a broken unit test,
you should fix the code,
or fix the test itself because tests can't go stale,
you need to get it fixed.
But, you know what? Sometimes reality
happens in shipping of feature
and your build is not working
because this test is failing and you can't figure it out.
Whatever the reason being,
you can ignore it so it's no longer run,
but then I would strongly recommend you do something
like add it to do or conversely,
you can also add the Hack
and that will show
up in your test list to go fix.
So, let's talk about theories because I think
that's one of the most powerful parts of
xUnit is the ability to
use the exact same code, the assertion,
and so they arrange action in the search,
easy for me to say after talking all day,
and have multiple scenarios test
without having to keep copying code.
We saw an example of
the inline data and that's where we're passing data
directly from the inline data attribute
into these parameters on the unit test method itself.
That's pretty straightforward.
Well, let's talk about some additional
powerful things that we can do.
We can say, hey,
there is a member that I have access to,
because it's either in the class or within
the referential patterns where I can return data.
So, this test data method
is returning an enumerable object,
each of these objects then get mapped
to the parameters of the test itself.
>> Okay.
>> Now, this is important
if you've got something that's more
complicated than adding an inline data.
For example, when I was working in insurance,
the way this actuarial tables where we had
all these parameters were thrown in,
I didn't want to sit there and type
every single line of Excel
in the samples and
the acceptance criteria into inline data,
but I could write a method that would then read
the Excel file and do
a yield return to return those values and map it.
>> Okay.
>> If the accountant added more data,
then I just swap out the Excel file,
I don't have to change my code.
>> Okay.
>> So, that's extremely powerful.
The third option is we can have a class
that implements enumerable objects and do it that way.
To be honest, I haven't used this in
real life but I just felt important
to show our viewers the data table.
But the two main methods I use for
simple tests where I have a few cases
or a few parameters I use inline data,
and then it's easy enough to add
another scenario by simply copying that.
Let's say this is
100 and negative three and this would equal 97.
>> Right.
>> And if for more complicated data.
>> Okay.
>> I'm sorry about test running.
For most people, you'll never have to change this.
xUnit and its runners run their tests in parallel.
There's a performance improvement,
you can't really find
a single core machine these days anyway,
so you might as well take advantage of that.
The way it decides what's parallel,
what serial is based on the class level.
>> Okay.
>> So, any test inside a single class will all run
serial but test across classes will run parallel.
>> Okay.
>> Now this is a problem for
you and I can't
think of a situation where it wouldn't be a problem,
but if it is a problem for you,
you can disable that very
simply by creating what's called a test collection.
What you do is you attribute your two classes
with the collection attribute
and the string name, unfortunately,
it is a magic string,
but any test classes or fixtures that
share the same name of the collection attribute
will combine all those tests to run them serial.
>> Okay.
>> The other big change between
the prior frameworks and
xUnit is how we handle exceptions.
In NUnit there is
an expected exception attribute
that we could decorate the test with.
The problem with that,
and this isn't allowed
anymore but let's just pretend it was.
If I could type Expected Exception, right here.
It's not in there anymore as we see this is something
different and then we
will put an exception type in there.
Well, the problem with that is what would
happen if you're arranged through that exception.
Never calls into the system or the test.
Sorry, I'll use my exceptional coffee cup to try
and calm the cough.
Then, the test would be marked as
passing because the exception didn't get through.
>> Right.
>> But we never actually exercised the system under test.
>> Right.
>> So, that pattern has been
decided to be an anti-pattern.
I don't want to say that
the folks who wrote those original frameworks were wrong.
It's just we've learned the different ways of doing
testing and we continue to improve and do better.
>> So, what we do now is we
assert that an operation throws an exception.
>> Okay.
>> So, I have this system under task,
now this is just hard coded to throw an error.
But, if I want to say calculator dot
add indot max value comma null.
>> Yeah.
>> The null should throw an exception,
then I can trap it here and I know that it's getting
thrown at the invocation of the system under test,
and not somewhere in the test itself.
>> Okay.
>> It returns the exception for us.
So, then we can start looking at what's the message.
If it's an argument null exception,
then we can look at what
the argument was missing and we can
do all kinds of assertions on that exception.
There's another way to do it that's a little more fluent.
This is the arrange
active search syntax more closely where we say
we're going to record an exception.
Honestly, they both did the exact same thing.
Dealer's choice, whichever one you want to use.
But, what's important to note is that we want to check
for the exception at
the invocation of the system or the test.
>> Right.
>> You might be thinking what about test
set up and test tear down?
So, in the other frameworks we've got
this ability to do a fixtures set up
that's going to execute once performing
your test or a test set up where we
want to execute something before every test.
So, instead of marking methods with
the set up and tear down attributes as we used to do,
we now use a constructor disposed pattern.
If you make your test fixture IDisposable.
Did you get that?
>> No.
>> Okay.
>> I'm busy.
>> Robert's phone just rang.
>> We'll wait. You guys wait too, right?
So, I market as IDisposable.
The constructor for the class will run before every test.
This is a test setup not a fixture setup.
Then, do these bills will run after every test.
So, for example, if you are creating something,
I do a lot of testing around any framework core.
I'm not testing in any framework core
but I'm testing my data access layer.
>> Right.
>> There are not that [inaudible] tests
[inaudible] integration test, whatever,
Iet's just call them tests,
and get away from the academic debate.
I want to have a brand new contexts before every test.
I don't want to have anything and change tracker,
I don't want to have any of that baggage with me,
so in my constructor,
I created new context.
At my dispose, I dispose off the contexts.
>> Okay.
>> So, that will happen again
before and after every test.
We can also set something up as what's called
a class fixture and when we use a class fixture,
what happens is we get the equivalent
of the fixture set up and fixture turn out.
I'm going to run this code one
time before all my tests are executed.
I'm going to run this code one
time after all my tests are executed.
>> Okay.
>> It's not a generally accepted pattern
among most people anymore,
but it's there if you need it.
The test set up and tear down
is really what we're driving people to
use more and more as opposed to having
this entire set of
tests depending on a certain set up and tear down.
The reason being is we want our test to be atomic.
>> Right.
>> We want every test to be
individual not dependent on other tests and things like
that and we tend to start
adding things into the tests that make them
less atomic if we had this whole fixture set
up and tear down.
The last thing I want to cover is capturing output.
Now, if you're running in, for example,
ASP.NET Core and you're using Kestrel,
all the output is done to the command window.
But, typically we're writing our
unit tests in a class library,
and we don't want to go through a whole bunch
of hurdle of adding and logging,
and things like that necessarily,
but we want to have output in there.
Well, that's actually very simple in that we
can, in our tests,
add in the ITest output helper
and then when we say output dot right line,
it's going to output to all of the standard out,
which by default is the console.
So, I can add additional.
So, if you're trying to figure out what's going on,
there are times when you're debugging
a task and it behaves
differently than when you're running it full on,
and you want to be able to do
the old school like me right when we were
doing classic ASP and alert made it here,
alert made it here,
alert made it here, right?
So, this allows you to do that if you're in
a situation where straight up
debugging isn't working for you.
>> Got it.
>> So, that's pretty much the power of X unit.
I know I glossed over some of the things,
but the most important thing
I want people to take away from this
is what works in Core
works in full.NET Framework. It's free.
That works with
pretty much any build server that you have.
I haven't yet had a situation where
it's not supported by a build server.
You get the road test capability or
the scenario based testing capability
and we try not to call it data driven
testing because then people
think well you're using a database.
Even though it's in
line data so we call it scenario based.
>> Okay.
>> Then, we can control the parallelism and
then we trap exceptions
at invocation as opposed to anywhere in there.
>> Cool.
>> So, any questions about X unit?
There's a ton more in X unit
but these are the features
I think people are going to use most often.
>> Okay. So, again this is
test framework so you've shown us the scaffolding,
if you will, and then the tests you
write are typically going
to be independent of the framework?
Did the actual tests you write
depend on the framework you're using?
>> The dependency is mostly in the asserts.
>> Okay.
>> So, for example,
in X unit, it's assert dot equal.
In N unit, it was,
if my memory serves,
assert dot is equal or are equal.
I don't remember the exact. Some of the syntaxes.
This is very dependent.
All these asserts come from X unit.
>> Right.
>> They're built into it.
So, that's depending on the framework,
some of the syntax things,
but this code here,
my arrange and my act.
>> Yes.
>> Totally independent of framework.
>> Right.
>> Right. We are depending on
the framework when we're looking at exceptions.
So, when we get into here,
this syntax here on line 22 and this syntax on line 30,
also dependent on the framework.
>> Right. Okay.
>> But, the actual invocation of
your system under test or the creation of your MOQ,
which we're going to cover and I believe
in the next episode.
That is all independent of X unit,
N unit, and B unit in this test.
>> Right.
>> Cool? Any other questions about X unit? No? All right.
>> All right, so that was a great overview of
X unit testing framework.
In our next episode, we're going to cover.
>> MOQ.
>> MOQ. Awesome. See you then.
>> Thanks for watching.