Online java test entry level. Program testing, JUnit. Java Test Prerequisites

I believe that software development is more than a job. I see myself as a craftsman who tries to become better every day. The "easiest" way to do this is to find some good tools and answer the following questions:

  • When should I use Tool X?
  • How should I use tool X?

Automated testing is a very important part of software development, but there are few posts on programmers' blogs about the tools used. This same article will allow you to look into my “tool box”. I'll cover 12 libraries and frameworks that I use to write unit and integration tests, and provide links to pages that will help you understand how to use them.

Let's look in my toolbox

Before you can use the tools described below, you must set up a build that automatically runs integration and unit tests. I have 2 notes on this topic:

  • Integration Testing with Maven describes how we can set up a Maven build with integration and unit tests in different directories.
  • Getting Started with Gradle: Integration Testing with the TestSets Plugin covers the same for Gradle.

Now you're ready to take a closer look at my tools. I've divided them into categories to make it easier for you to navigate.

So, here are 12 tools that I use for integration and unit testing.

Running tests

AssertJ provides a flexible API for writing assertions with useful error messages, improves the readability of test code, and allows you to turn tests into executable specifications that adhere to the desired domain-specific language.

Additionally:

  • Using Hamcrest in Testing covers how to use Hamcrest to write tests, as well as how to extend its capabilities with custom modules.
  • Turning Assertions into a Domain-Specific Language explains how to create custom assertions in AssertJ.
  • Writing Clean Tests: Replacing Assertions with Domain-Specific Language. Explains why we should replace JUnit's standard assertions with our own that use proper domain-specific language.

Data Access Code Testing

Fast database, useful for writing integration tests that run on local machine developer.

An extension to JUnit that can be used to initialize the database to a known state before running each integration test and populate the database with the necessary data. DbUnit has its drawbacks, but it is very useful tool, which allows you to separate test data and test code.

Additionally:

  • describes the key components of DbUnit that you need to know to write tests using DbUnit.
  • provides five rules for writing the best tests for data access code.

While looking for test tasks for Java programmers, I came across an interesting site (Avast users should not go, a script Trojan is detected, others are apparently fine) - http://www.betterprogrammer.com. It tests the qualifications of Java programmers in the simplest way, but in an automatic way: offering to write several functions (methods) of increasing complexity and copy the code into the TextArea. Next, the site engine does something with the tasks (no less than a unit test), calculates a certain qualification index based on the “speed-quality” criteria and gives the final score in the following form:

Then the questions begin. I myself programmed in Java for the second time in my life (and therefore simply skipped complex tasks), so 82% on this test correspond to the level non-java programmer. How much, then, should Java Junior, Java Programmer, and even more so Java Senior recruit?! What result can you expect from present java programmer - 90, 95, 99? And finally, what if the “programmer” scores less than 82, but nevertheless applies for some kind of job?!

Testing is not always fun and interesting. This process is usually quite lengthy and sometimes full of monotonous work. It seems that just recently programmers used standard output or a debugger to test java classes.

In this article I will describe the JUnit 4 library, which greatly simplifies and automates the process of writing tests.

To demonstrate the main capabilities of the JUnit Framework, let's write a primitive class in Java and mock it. This class will have two methods - finding the factorial of a non-negative number and the sum of two numbers. In addition, the class instance will contain a method call counter.

Public class MathFunc ( int calls; public int getCalls() ( return calls; ) public long factorial(int number) ( calls++; if (number 1) ( for (int i = 1; i

Now let's write Unit tests. To do this, we will create a class with a number of test methods. Naturally, a class can also contain ordinary auxiliary methods. In order for the test runner to determine who is who, test methods must be annotated with @Test.

An annotation can have the following parameters:

  • expected - indicate which exception will be generated by the method (see example below);
  • timeout - after what time in milliseconds the test will stop running and count it as unsuccessful.

If you want to indicate that a certain test should be skipped, then mark it with the @Ignore annotation. Although you can simply remove the @Test annotation.

There may be times when you need some context, such as pre-created class instances, to run each test case. And after execution, you need to release the reserved resources. In this case you will need @Before and @After annotations. The method marked @Before will be executed before each test case, and the method marked @After will be executed after each test case.

If initialization and release of resources needs to be done only once - respectively, before and after all tests - then use a pair of annotations @BeforeClass and @AfterClass.

And here is the test class itself with several test scripts:

Public class MathFuncTest ( private MathFunc math; @Before public void init() ( math = new MathFunc(); ) @After public void tearDown() ( math = null; ) @Test public void calls() ( assertEquals(0, math .getCalls()); math.factorial(1); assertEquals(1, math.getCalls()); math.factorial(1); assertEquals(2, math.getCalls()); ) @Test public void factorial() ( assertTrue(math.factorial(0) == 1); assertTrue(math.factorial(1) == 1); assertTrue(math.factorial(5) == 120); ) @Test(expected = IllegalArgumentException.class) public void factorialNegative() ( math.factorial(-1); ) @Ignore @Test public void todo() ( assertTrue(math.plus(1, 1) == 3); ) )

The calls method tests the validity of the call counter. The factorial method checks whether the factorial is calculated correctly for some standard values. The factorialNegative method checks that an IllegalArgumentException will be thrown for negative factorial values. The todo method will be ignored. Try removing the @Ignore annotation when you experiment with the code.

The assertTrue method checks whether the result of an expression is true. Some other methods that may come in handy:

  • assertEquals - the expected result and the received result match;
  • assertNull - the result of the expression is null;
  • assertNotNull - the result of the expression is different from null;
  • assertSame - the expected and received objects are the same object.
  • fail - the method generates an AssertionError exception - we add it where the program execution should not go.

In our modern world IDEs can find and simply run tests in a project. But what if you want to run them manually using program code. To do this, you can use Runner. There are text versions - junit.textui.TestRunner, graphic versions - junit.swingui.TestRunner, junit.awtui.TestRunner.

But a little more modern method is the use of the JUnitCore class. Add the following main method to the MathFuncTest class:

Public static void main(String args) throws Exception ( JUnitCore runner = new JUnitCore(); Result result = runner.run(MathFuncTest.class); System.out.println("run tests: " + result.getRunCount()); System.out.println("failed tests: " + result.getFailureCount()); System.out.println("ignored tests: " + result.getIgnoreCount()); System.out.println("success: " + result .wasSuccessful()); )

And the execution result:

Run tests: 3 failed tests: 0 ignored tests: 1 success: true

In more earlier versions In order to write a JUnit test class, it was necessary to create a descendant of junit.framework.TestCase. Then it was necessary to define a constructor that takes a String as a parameter - the name of the method - and pass it to the parent class. Each test method had to start with the prefix test. The setUp and tearDown methods were used to initialize and release resources. In short, horror. Well, now everything is simple, yes.

That's all for today. I'm sure the JUnit Framework will help you a lot. Comments and questions about the article are welcome.




Top