I am using IntelliJ to write some integration tests.
Project Structure:
/src
/main
/java
/com.myCompany
/dir
/email
/test
/com
Over time, I will be writing unit, integration, and performance tests. However, I’m confused about how I should structure my directories for testing. I also don’t understand how package naming relates to testing. For instance, I’ve created a basic test that looks like the following:
package com.myCompany.dir.email;
import junit.framework.TestCase;
import org.junit.Test;
public class EmailTest extends TestCase {
private final String username = “[testAccount]”;
private final String password = “[testPassword]”;
#Test
public void thisAlwaysPasses() {
assertTrue(true);
}
}
Unfortunately, I can’t even get that test to run. I get errors ranging from:
Error running All unit tests: Package not found in directory
to
No tests found.
Any insights are much appreciated.
It is a good idea to have your tests packages mirror the package structure of your classes under test. In your concrete case it should look like this:
/src
/main
/java
/com
/myCompany
/dir
/email
MyClass.java
/test
/java
/com
/myCompany
/dir
/email
MyClassTest.java
Regarding your part of the question about Unit-, Integration- and Performance-Tests. We usually follow either one of the following approaches (it kinda depends on the project size):
Create completely separate projects for Integration-Tests (and Performance Tests). In there you place your Tests within an identical package hierachy.
Simply place your Integration-Tests (and Performance Tests) in the same package as your Unit-Tests, but give them some common suffix (e.g. MyClassIntegrationTest.java)
there's no need to extend TestCase--the rest of your code is probably fine.
assuming you're using Maven directory structures (you appear to be), be sure you created a folder structure for tests which looks like: src/test/java/com/myCompany/dir/email--your class needs to be in a folder which matches its package name,
the extra quote in "[test"Password"]; -- you need to remove or escape it.
I'm guessing that #1 is the cause of the exception you're currently seeing.
Related
I am using Eclipse.
2 folders: src/test and src/main
Both have a package with same name: Academy.
The Academy package in src/test has in it a class name: Base.java
The Academy package in src/main has in it a class name: HomePage.java
In the HomePage.java class, extends Base is not detecting base class in it.
This is the code inside HomePage.java
package Academy;
import Academy.Base;
public class HomePage extends Base{
}
There is a red line on Academy.Base and on Base. It tells to make Base class, but it is already there. I tried to save the file. I tried to make new project too. Please Help. Thank you.
Here is the reference image:
You are using Maven as the build system for your Eclipse project.
Maven does not allow a class in your main tree to depend on a class in the test tree. It prevents this by telling the Java compiler and runtime that classes and resources in the test tree are not in the build time and runtime classpaths for the main code. That is why you are getting the compilation error.
Solution:
Move the Base.java class into "src/main/java/Academy" directory.
You commented:
It's just 2 packages with same name, inside 2 different folders. whether it's test or not, it should still inherit with extends.
Sorry ... but you are wrong. It does matter which tree you put the classes in. This is a Maven project, and Maven is "opinionated" about these things. For good reason, IMO. But either way, Maven's opinion takes precedence ... if you choose to use Maven.
There are a couple of other problems:
A package name should start with a lowercase letter. Read this for example.
Solution: Rename Academy to academy1.
Non-code resources should not be in a "java" directory. Non-code resources in a "java" source directory won't be on the runtime classpath ... and won't be included in (regular) JAR files.
Solution: Create a "resources" directory and put it there.
The import Academy.Base; is redundant. It is not necessary to import a class in the same package.
1 - Alternate solution: don't ask other people to work on your code, or help you with it. If other people don't ever need to read your code, it only matters to you what your code looks like. The compiler doesn't care. Only humans do.
The import was irrelevant.
Your src/main/java/, src/main/resources/ are packed for your main product, probably something like E2EProject1.jar.
Your src/test/java/, src/test/resources/ are packed in your unit tests, probably something like E2EProject1-test.jar. These test classes are kept outside your main product, but have the main product on the class path as dependency.
So it should be something like:
src/main/java/Base.java
src/test/resources/data.properties (or src/main/resources/)
That the packages are named identical is for being able to test (implicitly import) non-public, package private classes of src/main/java in unit test classes in src/test/java.
Solved the above error by following these steps:
Right click on project->Build path->Configure build path->source tab
then search tab search under your project src/main/java
and change "contains test sources" from No to Yes
and apply the changes
I have a mock class with a trivial implementation of a service I provide from a module. I'm using OpenJDK 11.03, gradle 5.2.1 and IntelliJ 2019.2.
In /main/code/myPackage/myService.java I have:
package myPackage;
class myService {
public abstract void someFunction();
}
And in my test/code/somePackage/myMockService I have:
package myPackage;
// no import, they're in the same package.
class myMockService extends myService {
#Override
public void someFunction() { System.out.prinln("Hello World"); }
}
In my main/code/module-info.java I have:
module myModule {
exports somePackage;
}
I've tried several variations on a test/code/module-info.java, without success. For example:
// "open module" lets anyone use reflection within (mostly JUnit 5 in my case)
import myPackage.myService;
import myPackage.myMockService;
open module myTestModule {
exports myPackage;
provides myService with myMockService
}
The above module-info.java spews errors about how "module name myTestModule does not match expected name myModule", "package 'myPackage' is not visible" (from myMockModule.java), explaining "package myPackage is declared in module myModule but module myTestModule does not read it"
On the other hand, with the following module-info.java, I get a different batch of errors (below the code)
import myPackage.myService;
import myPackage.myMockService;
open module myModule {
provides myService with myMockService;
}
Without a requires myModule;, every reference to the main code branch from my test code gives an "error: cannot find symbol". With a requires myModule;, I get an "error: cyclic dependence involving myModule".
So... my tests can't be in a different module. AND they can't be the same module! [long string of expletives deleted]
How do I introduce a mock version of a service in test code rather than creating an entirely different module/gradle sub-project?
Or is this simply a case where that's not possible, and while you can have a separate test module-info, you can't do much with it?
Or is there some way to dynamically load things at runtime such that I don't have to put every little mock service in any module-info, test or otherwise? Such that ServiceLoader.load() will find them. Hmm... perhaps extend ServiceLoader and wrap its usage in main code such that it'll use the right one either in production code or test code...
a) Welcome to "Testing in the Modular World"!
TL;DR https://sormuras.github.io/blog/2018-09-11-testing-in-the-modular-world.html
Having one or more dedicated test modules is good. With all bells-and-whistles, read module-info.java declarations. Those test modules are your main modules' first clients. Just make sure, that your build tool packages all main modules before compiling and running the test modules. Otherwise you don't test your main modules as close as possible to reality — others will consume your main modules as JAR files. So should you. This solves all issues with services and multi-release JARs as well.
Now the interesting part: in-module testing, also named white box testing. Or how do test types residing non-exported packages or package-private types in exported packages? Either use a build that knows how to patch test modules into main modules (or vice versa) at test compile and/or test runtime. Like pro or Bach.java (which I maintain), or in your case of using Gradle, see b)elow part of this answer.
b) Gradle and Java main, test, … modules are not friends out-of-the-box, yet
Best plugin-based solution: https://github.com/java9-modularity/gradle-modules-plugin -- which honors the pass theses java command line options at test runtime module-info.test configuration file (which I invented). Here you basically desribe your test module requirements via verbose command line options, although a perfect DSL already exists: module-info-java ... loop back to a) and the module-aware build tools.
c) IntelliJ IDEA and Java test modules are ... improving!
https://youtrack.jetbrains.com/issue/IDEA-171419 module-info.java support in 2019.3
https://youtrack.jetbrains.com/issue/IDEA-222831 module-info.test support, soon?
I have a package structure containing Unit Tests that corresponds the production code. When I do the refactoring, I often move classes to different packages. In that case I also have to manually move the corresponding Unit Test class to the new package and sometimes I forget to do so. Is there any solution, how to move the corresponding JUnit test class to a corresponding package automatically?
I use Eclipse Luna.
There is a plugin called "MoreUnit" which is very helpful for everything concerning working with JUnit tests. It supports what you are looking for. Have a look at http://moreunit.sourceforge.net/
I have some JUnit tests that contained in a .jar that is intended to be used as a library. The library contains some tests that should be run whenever the library is used in another project.
However when I create a new project using the library and run JUnit on it in Eclipse then the tests in the dependency .jar don't run / don't get detected by the JUnit test runner. I get the message:
No tests found with test runner 'JUnit 4'.
Is there a way I can configure the dependency .jar so that the tests will run alongside any tests that might be contained in the main project?
Basically I want the dependency .jar to "export" the tests to whatever projects it is used in.
I'm using Eclipse Juno, JUnit 4.10, and Maven for the dependency management.
EDIT:
The point of this library is to be able to help test projects that use it - i.e. it runs some specialised tests. This is why I want to be able to import the library .jar and have it contribute the extra tests to the importing project.
You can try Maven Surefire.
In some cases it would be useful to have a set of tests that run with various dependency configurations. One way to accomplish this would be to have a single project that contains the unit tests and generates a test jar. Several test configuration projects could then consume the unit tests and run them with different dependency sets. The problem is that there is no easy way to run tests in a dependency jar. The Surefire plugin should have a configuration to allow me to run all or a set of unit tests contained in a dependency jar.
This can be done as follows (Junit 3):
Ensure test jar contains a class which has a static suite() method
import junit.framework.Test;
import junit.framework.TestSuite;
public class AllTests {
public static Test suite()
{
TestSuite suite = new TestSuite( "All Tests");
suite.addTestSuite(TestOne.class);
suite.addTestSuite(TestTwo.class);
return suite;
}
}
Then in the project using the test-jar dependency:
create a TestCase:
package org.melati.example.contacts;
import org.melati.poem.AllExportedTests;
import junit.framework.Test;
import junit.framework.TestCase;
public class PoemTest extends TestCase {
public static Test suite()
{
return AllExportedTests.suite();
}
}
Now the tests will be found.
I think that making a library of unit tests (#Test annotated methods) is a bad idea. However, making a library of reusable test components is a good one. We've done this in a few open source projects, and you can take a look how it works.
One Maven module exports test components (we call them "mocks"), from src/mock/java directory. Exported artifact has -mock classifier. See rexsl/pom.xml (pay attention to highlighted lines).
Mock artifacts are being deployed to Maven Central, together with usual artifacts: http://repo1.maven.org/maven2/com/rexsl/rexsl-core/0.3.8/ (pay attention to ...-mock.jar files)
Modules that need that mocks can include them as usual artifacts, for example rexsl-core/pom.xml (see highlighted lines):
Then, in your unit tests just use the classes from that mock libraries, like regular builders of mocks, for example: BulkHttpFeederTest
That's how you can make your test artifacts reusable, in an elegant way. Hope it helps.
#Mikera,
I find that this may help you. Just extend the Testcase Class to one of your java classes in project and you can run that particular class to run it as a JUnit Test.
I am not sure that this is desirable - On the one hand, if you use a jar, its behaviour might be influenced by the external context, e.g. other libraries in the classpath. From inside the jar, there is no simple way to analyse this context and to adjust the tests accordingly. On the other hand, if you write and compile a library, you should test it before packaging it as a jar. You might even want to not include your tests.
If it is really important to you to run the tests again, I would be interested in what could make them fail without changing the jar. In that case, however, you might want to extend the testrunner. As far as I know it uses reflection. You can quite easily load jars in a classloader and go through all their classes. By reflection you can identify the test classes and assemble testsuites. You could look into the testrunner for an example. Still, you would need to start this process from outside, e.g. from inside one of your test classes in the client project. Here, QATest's approach might be helpful: By providing an overriden version of testsuite or testrunner, you could automate this - if the client uses your overridden API.
Let me know if this rather costly approach seems to be applicable in your scenario and I can provide code examples.
Why should the user of the jar run the test cases inside the jar!!! When the jar is packaged and delivered, it means that the unit tests are run successfully.
Typically, the jar itself should be either treated as a separate project or as one of the modules. In both the cases, unit test cases are run before its delivered.
I'm trying to create this directory structure in Maven Java project:
pom.xml
/src
/main
/java
/com
/XXX
Foo.java
Bar.java
/test
/java
/com
/XXX
FooTest.java
BarTest.java
/spikes <---- I'm not sure about the right English word for them
/com
/XXX
MockedHttpConnection.java
Thus, in two tests FooTest and BarTest I can use the same MockedHttpConnection, which is perfectly decoupled from them both, staying at the same time in the same package with them. What do you think about this approach? I have a feeling that I'm reinventing a wheel, but I can't find any patterns for this mechanism in Java.
If MockedHttpConnection is your own class I'd suggest you to store it under /test/java/com/testutil.
If it is third party class, just add jar to your classpath.
I'd sugget having it in your test package because in the end is testing code.
It's the same as the application. You don't just store your application main class under main. You store it and everything it needs to be executed.