Transcript
This transcript was autogenerated. To make changes, submit a PR.
You. Hello and welcome to my talk
concerning making the jump to Junit five from Junit four using the
spring framework. My name is Jonathan Meek and we'll go ahead and get started.
So a little bit of background on myself. I've been an active Java developer since
2010. The oldest version of Java I've ever worked on was Java
1.6. I was doing this in the process of working
on network provisioning software, which was a lot of fun of
currently training for my first half marathon. Originally this was set for
March of this year that's been postponed, so I'm just going to continue
training. I have two cats, Deacon and Reina. And as you
see here in the photos, on the left hand side is Deacon, on the
right hand side it's Reina. So the other part is I'm
married to the most talented agile coach Baker known to
me. So she currently does consulting with executives.
But there's a lot of shop talk that happens and she's usually coaching me on
how to be a better developer. Here in the little
corner here, you see this wonderful little treat she's made. It's peanut butter Reese's
cup. So that's just a little bit of background onto me. But let's go ahead
and jump into what you came for, which was understanding
that migration path for Junit four to junit five.
So before we talk about that, from my perspective, I believe that there's
a deeper problem that we're not talking about. Test frameworks are usually the last thing
to be upgraded into those code base and I think it comes from the idea
of we want things to continue to work. And kind
of a side note, Junit was originally released in 2006 and
I think as those comic illustrates here, right, this is our attitude.
We never touch the ancient code. But the problem is
when it comes to our testing frameworks, especially for those of us who
are practitioners of TDD, this should be the first thing we should be looking at
and we should be considering how to upgrade these things because these are those
tools that are giving us the cadence that our software is working as designed
and intended. Another aspect, something we're not talking about
either. So I pulled this from last year's presentation
track for a developer conference. Notice that there arent a
lot of things talking about migrating beyond Java eight, the SE
eleven developer certifications and discovering modern Java.
A lot of things indicating towards that path but nothing
around those frameworks. Now granted, this is the code Java, but when I looked across
the whole programming track, there weren't anything. And to put it into context.
This was actually the conference I just recently presented at Devnexus last year.
And when I was talking at that conference, that was something I pointed out again,
I think as a community, we have to start being willing to talk about
not only the cool frameworks we're using to develop our code and the cool features
of a programming language, but also those testing frameworks that we're looking
at as well. So, first question, it's just a parentheses swap out, right?
No. Junit five represents a major version shift and reorganization effort
by the Junit team. It actually breaks it down into three main projects now.
So you have the Junit platform, so that includes the test engine API
interfaces, as well as the Junit Jupyter, which contains
the actual implementation. So again, doing best software practice of decoupling
the interfaces from the implementation so changes can be made in the future while not
breaking compatibility. And then Junit vintage, which supports running Junit three
and four tests in junit five. So if you're listening to my last
comment, there's another question. Can't I use Junit vintage?
You could, and I would say why?
Because it's kind of kicking the problem down the road. I understand that
there are needs for older code bases where we can't exactly
go in and dive in and make those changes, but I would press
that. We may need to reevaluate that. And also, personal experience,
it's been that Junit vintage hasn't worked for me. Usually the
testing fails, it does something weird. So I would say that
Junit five can be introduced to an existing code base,
and also, if you're going to do it into an existing code base.
Right. You're going to have to be mindful of the fact that you're going to
make some changes there. With that in mind, you'll see some clarity and some
changes that happened in the annotations. So again, this is kind of why it's
not an easy one to one swap out rate. It's. There were some updates that
were made, and to me makes it more clear. You can see that the
at test annotation stays the same, but you can see for some of
these other ones, they've become more specific. Right. So before
all versus before class, and then the before becomes
a before each and after and after each. My favorite one is probably
the TDD ignore becomes a disabled for me. That's a little bit clearer in my
head. So you can see where at junit five they were trying to aim for
conciseness behind what they were saying and what they were doing.
Another thing you'll see is the packages name no longer is
test located at that level. Again, it goes back and reflects
the changes we saw earlier when I said that there was a separation of between
the implementation and the interfaces. So you see this
Junit Jupyter API test, and then same with the assertions,
again going back for that conciseness and that clarity of where things reside.
So now that we've kind of talked about the bigger pieces, let's kind of talk
through what does an upgraded path look like? So in this example we're going to
talk through with spring framework, with some of the other frameworks that are.
But there they have started going to having Junit five be the
default on new projects. So we won't go into detail that,
but we'll talk at least here. So at least with spring framework, right, you want
to make sure you have Java eight or higher. Again, this has used some of
the lambda functionality behind it in order to do this,
and then spring framework five or higher. So looking through the spring framework
setup, Springboot 20 eight release is actually
the first time you see Springboot five. And so you want to use that
version or higher. It actually became default in spring boot two four.
So in this example I'm actually going to show it using the spring two four,
because that's easier. And I want to show off some of the features that are
new to junit five. In that process, you want to make sure you upgrade your
dependencies in your palm XML, and then you want to swap out the following bits,
right? A run with becomes an extend with your spring runner becomes a spring
extensions class, and your before becomes a before each. And also if you're
using Makito, your junit runner class becomes a Makito extension and
a keynote with the runners and extensions. Kind of the cool thing is now
you're able to do many extensions where in the past you had
to choose between a singular runner. I actually ended up using this on a project
recently where I needed to
add in the Makito extension. So I was able to do an extend with Makito
extension class and it worked perfectly. No problems, no issues.
So something to keep note. And then also that last part of you can flip
to the earlier slide where it says the TLDR diff part two where we
talked about that packets guidance. And again when we demo it, we'll actually walk through
that. So not only is the same functionality there, but there are
a couple of cool features that I find extremely helpful. The at display
name allows you to add a human readable name to the test. I find this
great for developers who may not be as experienced in the code base
to be able to identify what exactly has gone wrong in a test. In the
past when my team has done those things, we've had to come up with some
sort of weird naming convention of should do this,
win this, then kind of pattern in the method
name. So this allows us to just be able to add something that's
a little bit more readable and also can potentially allow for inexperienced developers,
any of your scrum masters, to kind of take a look and understand where has
it failed, especially if they happen to be reviewing test case
results from a given setup. The other two that go hand in hand is parameterized
test and those CSV file source. The parameterized test allows you to
write programmatic tests where multiple inputs can be passed and tested individually.
The CSV file source allows you to point to a particular place and say,
okay, I want you to use this file to generate and pull in the information
behind that. So at this point we're going to do some live
coding. I put that in air quotes because of the fact of I've already done
it and I can actually switch branches over into the junit five,
but I want to at least try my best to go through it. So without
further ado, we're going to pop out and get started.
Okay, so to kind of show off, I'm first just going to run the
gradle. Sorry. I'm actually using maven, not gradle
on my work setting. I usually use gradle,
so I figured a lot of people are probably using maven, so I
figured to stick with that. So I'm just going to do a maven clean
test, prove everything works as it is. Right? No black
magic here, right? Because I feel that's important when we're
talking about, hey, I want you to go do this thing right.
All right, cool. So it runs through all the things, tells me
everything's good, has nine successes. Okay, so what
I'm going to do is I'm going to change this, but for two four,
and I believe if merge serves me correct.
Let's see, do I got a one? No. Okay, so we'll just go with two
four for now and helps if I use
the right keys. All right. And yeah, sure, we will
go ahead and do that part. Now. At this point it's probably going to scream
about a lot of different things. So the first place we're going to start is
with the controller test. And we'll work through the test first,
make sure everything looks correct. Those and then we'll work into the service and
whatnot. And then I'll at the end do the full set with
everything converted over to junit five. All right, so let's start with the
controller test. As you can see, all the assertions and all the things
arent screaming a little bit. So what we'll do is for now
I'm actually going to remove the imports for the time being.
And as a side note, with the application itself, this is a simple
rest endpoint that allows us to be able to do a couple of things.
So just real quick I'll show you got
a simple controller of coffee, one of my favorite things
to drink. Unfortunately because of the time of day I'm not drinking one right now,
but it's one of my favorite things. So I have an endpoint where I
can get all the coffees. I can get a coffee by its id and then
I can get the best rated coffee. So that's what my testing
does. And all this is backed up by an h two in memory database
just for simple simplicity and whatnot.
So this is kind of a general view of what the application looks
like. All right, so we change this to an extend
with and let's see if whoops
helps if I don't, but the buttons. I'll let the
system give me a hand here a little bit. All right,
change that runner into an extension as I said earlier.
And again, the system is going to help me a little bit. I'm also going
to go ahead and delete the not needed piece
there. Okay, so keep scrolling down. And in this case, again with the control
treat. We're using mock MVC. All right, so let's see.
I want to do that import. All right, cool.
All right, let's see. What's it mad about?
Okay, let's scroll down the assert.
So this needs to be versions to make this work because
it moved from assert to assertions in GNH live.
All right, still not happy with that. Let me try
and import. Yes, there we go.
So I'm actually going to use the junit Jupyter API.
All right, cool. Now everything looks correct here. Let's scroll
back up. All right, cool. Nothing's yelling at
me. Everything seems to be okay. All right, so I'm just going to hit Ctrl
save real quick. All right, so that one is good at this point.
Now I'm going to move into the service. The service may be a little bit
more tricky because I know
that there was one thing I had changed here with this before.
It may yell at me a little bit either in the runtime and whatnot.
We'll wait and see what happens here because at one point in the development
of the code, it was demanding that something be static. So just as
a heads up, we may run into a little bit of a bump here.
All right, so I'm going to go ahead and delete the things that it's yelling
about for now. Again, I could probably walk through and type
and correct them, but we'll do this last one
because it's just simply adding that and oh yeah, the Jupyter
API assertions. There we go. That's correct.
All right. Deadwidth right now, imported the right thing.
It's going to be like, what is this? As I said earlier,
it should change to an extension in this case. I know that with Makitoj junit
runner, it changed name into Makito extension. So we
do that. Okay, so we see all those mocks and the
jacks. Okay. And we'll try
before each helps
if I import it. Yes, it's imported.
All right, let's do that.
Cool.
All right, so the thing here that changes,
right, is in junit four, you're able to do an expected
that's no longer the case. In five, this particular ability
and annotation does not exist. What you have to do instead is
actually a lambda function.
So this is that first place where we see something that happens.
So we'll do an assert throws.
And with that assert throws, I tell it. Okay, here's the expected
type. So I'm going to tell it exception class,
I'm going to do a comma and this is where I insert my lambda.
And what I'll do is actually the command I care to call or
sorry, those method I care to call. So it's actually this one.
So I'm just going to use the right keyboard bindings,
paste it in. All right, cool. And also get rid of that.
So kind of the cool thing is you now get rid of the wonderful
error, your id or editor yelling
at you and saying, hey dude, this is never used.
You don't do anything with it. Right. It actually gives you a purpose and allows
to avoid that problem. All right, let's see.
Static import of the assert throws.
Try that again. All right, it's just
going to be mad at me for a second. I think I misspelled something.
That's usually my biggest problem.
Those we go nice. Now everything looks
nice and pretty. So let's go back up here to the
top, make sure we're not missing anything. Okay. So it's going to tell
us get rid of line eleven. All right, cool. So now
I hit save. So next thing I'm going to do is just going
to rerun my test.
All right, cool. Everything again works. No problems.
All right, so all I've done thus far is just move us over from junit
four to junit five. But I've not done any of the new features around that.
So what I'm going to do is actually go into the controller test and I'm
going to show off the display name. So we'll
take this first one here. So when I do at display name
and it gives me this option, I am able to define that human readable
thing. So right now you can see on line 34 should return all
coffees when hitting default resource with get.
So right now what I'm going to do is quickly kind of come up with
a kind of standard, so to speak, treat, I would think. Okay,
so return all coffees.
See, I want to do that particular endpoint
and then I expect treat to be actually get
and then that endpoint. And then, okay, I expect that to be a 200.
Okay, so you can see here, I'm kind of using a quick shorthand
to be able to communicate what the expected output and ability
of it is. Right. And when I run this. So let me
do that and we'll do those maven clean install.
Actually, I wonder, I'm going to try running,
doing the run test here in visual studio code.
Because if I do that, it will probably show it more clearly
in its test runner results.
All right, looks like it completed. I pull this open.
All right, see, so right here in the test report.
Right, you have return all coffee. Use the dash. The get 202 hundred.
Sorry, get default endpoint
200. Okay. Right. What I told it to be here.
So again, just one of those things that helps with readability, helps with
some clarity around what it is that you're looking for.
All right, so next thing I'm going to do is
we're actually going to try out the
parameterized test. Again with the parameterized test,
what we would do is we would just give it a list of parameters and
give it a csv.
So in this case, I'm going to cheat a little bit.
I'm actually going to go ahead and jump over into those junit
five completed setup and we'll walk through it and I'll explain
how all those pieces come together. It will save us a little bit of
time here. So let me pop here into
the terminal,
check out five
complete new
computer and I forgot to put treat little keyboard shortcut.
There we go. But all
right, cool. Now I'm actually in the right place. So when I scroll
up you can see here where I've given all the display names,
tried to put a put, tries to do a put on this resource, get a
405 method not allowed, right to provide that information on
the display name. And actually the test
I'm looking for is in the service. I keep saying the
wrong thing. All right,
let's see. Here we go. So it should return a single copy.
It returns a single copy by the coffee's id.
Now with this app I
have this Testdata CSV, right with those CSV file source.
This resource starts off looking at the test resources
folder in that class path. So I've pulled up the test data
CSV to give the context.
You'll see here the
past index of zero, one, two and
then the coffee id, the coffee name, the coffee
type and its rating. So when I look
at the coffee test service test, you notice here
I've got parameterized test. I've told it I want you to take the CSV
file located here and you notice the parameters
that I've passed in, right? So you got 12345.
When I look at the test CSV 12345.
So again you want those to match up or it will throw an error message
to you saying hey, you've got a couple of things in the CSV
but not the same thing in the method name. What are you doing?
So you can see here where I actually walk through and I
parse the id that I passed in. I tell it
okay go find by this and then return an optional of
the mocked coffees that I created up here at the top that
match that id giving that information and giving that
viewpoint, right? So then I say okay, go get the coffee id
when I do my asserts, right? Okay here's the pulled single coffee
id and here's the expected name and migrating and the equality
on it, right. So now what you're going to see instead of nine tests you
should see eleven tests when we run this because of the
fact of I have three items, right. Previously I was
testing for just the one so I've added two more. So ten on eleven.
So if I run the whole data set here.
Okay, no thanks. Thank you intel or sorry vs
code but I don't really care to do that right now. All right,
so we will run all the tests here again prove no
magic.
Probably helps if I use those maven w clean test
and you can see here I had eleven tests run.
It's not going to show there. Not taking it there. My bad.
But you can see the test run were eleven instead of nine this code time
because we added two more tests by being able to use the parameterized test.
All right, that concludes those. So here are the resources I
use to pull this talk together again, I don't claim to be an expert and
I always try to do my best to give credit where credit is due.
In keeping with that those I want to give a special thanks to
my teammates on the tax commons at the Home Depot. They were instrumental
special shout. But to Jeff Anderson who gave
a lot of feedback on this talk, helped make this talk better,
as well as Jonathan Davis who helped me with Obs and getting this
all pulled together. Lastly, and not least,
I wanted to give a shout out to dinner bursary.
He was my mentor when I first started into Java,
told me about the conference I did my first presentation at this year at
Devnexus. Without him I would definitely not be doing this today.
So a huge thank you to him. All right,
I've reached the end. Give me a second here and I will actually pull
together my twitter handle as
well as where you can find the code behind all this awesome work.
So that way you can take a look see.
All right, let me pull up visual studio code
and I'm going to put it on a try to put it on
a blank area. All right, so Twitter could like to
find me. I am ehawk 61
on whoops, provided I can type ehawk 61
on Twitter. As far as the GitHub repo,
if you go to GitHub.com 61,
you'll find me. And actually I'm going to
see if I can follow the link real quick because that's going to be faster
than me trying to remember it. When you get to the
page. See my face here and what you're
looking for in those repos is migrating junit 405 and
I will actually pull that together. Go back here into visual
studio code and
give the full link. Well, provided I actually copy and paste.
Try that again.
All right, so GitHub.com ehoc 61
migrating four junit five so
you can find the code for all this. I'm in the process of pulling together
slides to put up with the code that are exact duplicates of what I presented
today. Feel free to reach out if you have any
questions, concerns. Thanks again for the opportunity to speak today.
Be safe out there and looking forward to when we're all able to
be back together and in person. See ya.