Java – write the first JUnit test
So I've read the official JUnit documentation, which contains a lot of examples, but (like many things), I've started eclipse, I'm writing my first JUnit test, and I've killed some basic design / concept problems
So if my widget unit test is testing a target called widget, I think I need to create a considerable number of widgets in the whole test method Should I construct these widgets in the widget unittest constructor or in the setup () method? If you use 1-to-1 widgets to test your method, or is it best to reuse widgets as often as possible?
Finally, how much granularity should there be between assertion / failure and test methods? Purists may think that there should be one-to-one assertions in a test method, but according to this example, if the widget has a getter called getbuzz (), I will eventually get 20 different test method names from getbuzz ()
@Test public void testGetBuzzWhenFooIsNullAndFizzIsNonNegative() { ... }
Rather than a way to test many scenarios and carry a large number of assertions:
@Test public void testGetBuzz() { ... }
Thanks for any insights from some JUnit masters!
Solution
pattern
Interesting question first – the final test mode I configured in the IDE:
@Test public void shouldDoSomethingWhenSomeEventOccurs() throws Exception { //given //when //then }
I always start with this code (smart people call it BDD)
In a given case, it is unique for me to put test settings in each test. > When is the ideal single line – what you're testing. > It should then contain assertions
I'm not an advocate of assertions, but you should only test a single aspect of behavior For example, if the method should return something and have some side effects, create two identical tests, giving and when to use them
The test pattern also includes throwing exceptions This is to handle annoying check exceptions in Java If you test some code, you won't be bothered by the compiler Of course, if the test throws an exception, it will fail
establish
Test setup is very important On the one hand, it is reasonable to extract common code and put it in the setup () / @ before method Note, however, that when reading tests (readability is the greatest value in unit testing!) It's easy to miss the setup code that hangs at the beginning of the test case Therefore, the relevant test settings (for example, you can create widgets in different ways) should test methods, but the infrastructure should be extracted (set up common simulation, start embedded test database, etc.) Improve readability again
Did you also know that JUnit creates a new test case class instance for each test? So even if you create the CUT in the constructor, you call the constructor before each test. It's a little annoying
granularity
First your test and consider the use cases or functions you want to test, never consider:
Shouldturnofenginewhonoutoffuel() is good, testengine17() is bad
More about naming
Testgetbuzzwhenfoisnullandfizzisnonnegative what does the name tell the test? I know what it tests, but why? Don't you think the details are too sweet? how:
@Test shouldReturnDisabledBuzzWhenFooNotProvidedAndFizzNotNegative`
It describes the input and your intention in a meaningful way (assuming that the disabled buzz is some kind of beep state / type) Also note that we no longer write the getbuzz () method name and null contract for foo (instead, we say: when foo is not provided) What if you replace null with null object mode in the future?
Don't be afraid of 20 different test methods of getbuzz () Instead, consider the 20 different use cases you are testing However, if your test case class grows too large (because it is usually much larger than the test class), you can extract it into several test cases Again: foohappypathtest, foobogusinput and foocornercases are all good, foo1test and foo2test are all good
Readability
Strive for short and descriptive names Few lines were given at that time nothing more. Create builders and internal DSLs, extract methods, and write custom matchers and assertions Tests should be more readable than production code Do not over simulate
I found it useful to first write a series of empty test cases called good Then I went back to the first one If I still understand what I test under what conditions, I implement the test build class API during this period Then I implemented the API Smart people call it TDD (see below)
Recommended reading:
> Growing Object-Oriented Software,Guided by Tests > Unit Testing in Java: How Tests Drive the Code > Clean Code: A Handbook of Agile Software Craftsmanship