I have an issue with some gradle task that should run tests. Since this is some legacy from ant tasks we do not want to include them into our test suite. Especially considering that those ant ones are in testng, and those made by us, and used on regular basis are made using spock and junit.
The problem is that those tests are using some context which works pretty well when I run those tests under eclipse IDE, but it fails if I try to do sth like:
task testNgTesting(type: Test, dependsOn: testClasses){
useTestNG()
includes = ["**/*IT*"]
}
But when I try to use that task I get errors like "org.hibernate.MappingException: Unknown entity:" or "java.lang.IllegalArgumentException: No query defined for that name"
Actually the problem is deeper. Gradle is trying to be smart and from whatever folder it has defined it puts classes files into classes folder, and all the other files into resources. When persistence.xml is loaded it scans for annotated entities starting with classpath root for folder it is present in (i.e. build/resources/main). Since all those classes are in build/classes/main it fails to find them. The workaround I've made is introduce two copy tasks. one named is copying persistence.xml into classes folder, and another is moving this file back to resources after the tests are finished. You might want to use something like
testNgTesting.finalizedBy(cleanAfterIntegrationTests) to make sure the cleanup occurs even if there are some tests that fails.
Related
There are a ton questions regarding getResource or getResourceAsStream returning null and so far I understand the issue but I currently cannot properly solve it.
I have a resource file which is used by some class in production. The file is located in
app\src\main\res\raw\some.def
The class SomeManager uses this to access this file:
InputStream stream = SomeClass.class.getResourceAsStream("/res/raw/some.def");
This succeeds when running the debug variant of the application on the emulator and it also succeeds when running the debug variant of the instrumented tests. I assume because the resource is properly packaged into the jar?
However when I run some local jUnit tests in android studio this resource is not found. I did not fully understand what is exactly executed when running a local test and I am not sure how to provide the resource file in a way that can be loaded in a test.
I would like to avoid doubling this resource file because it is actually something I want to test, I also would like to not change the getResourceAsStream path because this is the production file I want to test.
I am using gradle and android studio if that matters.
I debugged this issue with Sysinternal's Process Monitor and realized that when I run code locally on my machine the resources are as streams are looked up from various different locations on disk. One of those locations is
<build_directory>/intermediate/classes/<build_type> where it is obviously missing.
The solution to this was to create a copy task that performs the copying and make it robust enough to work for all build types.
So I modified my app's gradle file and added those dynamic tasks:
android.buildTypes.all{ theBuildType ->
task "copyDebugAssets_${theBuildType.name}"(type: Copy){
from "${projectDir}/src/main/res"
into "${buildDir}/intermediates/classes/${theBuildType.name}/res"
eachFile { println it.name }
}
}
tasks.whenTaskAdded { task ->
// println "A message which is logged at QUIET level ${task.name}"
if (task.name.startsWith("process") && task.name.endsWith("Resources")) {
def partInBetween = task.name.substring("process".length(), task.name.indexOf("Resources")).toLowerCase()
if (partInBetween == "debugandroidtest") {
return
}
def dependentTask = "copyDebugAssets_${partInBetween}"
println "Registering ${dependentTask} to ${task.name} for config '${partInBetween}'"
task.dependsOn dependentTask
}
}
I have really no idea on how to properly use gradle but the first statement generates as many copyDebugAssets_xxx tasks as there are build types. After syncing you can see and execute the in the gradle projects.
To avoid calling them whenever a clean or rebuild is done manually, the second part registers the copyDebugAssets_xxx copy tasks to the various process<Configuration>Resources tasks, which are then called automatically. So far I can run local unit tests in multiple build type successfully.
I have checked out a code from CVS and need to make changes to it. The code has 2 folders
Java
Test
The later has JUnit test cases. I'm not very familiar with JUnit but as far as my understanding is, the classes are duplicated in JUnit as class names. That's why I get the error in the test folder.
Class "xxxxx" already exists
I'm not sure how do I run this project without removing the folder test. Is there a way I can make eclipse ignore the JUnit test cases for now?
Go into the properties of the Eclipse project, open Java Build Path / Source and remove folder Test. Eclipse will then ignore the sources in that folder.
Test and normal java classes are merged together during build time, your error happens because the test classes have the exact same name as the normal classes. You should rename your test cases with some kind of prefix like Test to prevent them conflicting.
Doing things to work around the problem will only conflict later when you are changing the build platform, maybe your current build platform accepts it, but your future platform/editor may not, and then you have the real problems.
I'm facing a problem with JUnit tests. I have written an JUnitRunner which is used to execute the WrapperTest.
The WrapperTest generates a plain JUnit-Test and a needed file. If I want to execute the methods of the generated test, my Runner searchs in the Developement-Workspace for the "NeededClass".
I'm generating the needed class in the JUnit-Workspace and i want the tests to use this generated class file, so i can delete this file in my Develop-Workspace.
So, how do I execute the generated test in the JUnit-Workspace? (He shall look in the JUnit-Workspace for the needed file)
edit: OK, i found out, it's a ClassLoader problem... The Develop Workspace got another ClassLoader than the JUnit-Workspace, this causes weired errors, for example that a "class isn't the identical class Exception" (java.lang.ClassCastException: org.junit.runner.JUnitCore cannot be cast to org.junit.runner.JUnitCore). Looks like i have to fix this problem by reflection, what is very dirty.
Look into Maven and its build lifecycle. You can wire the code generation you are doing into the generate-test-sources phase and then have it participate as normal in the test phase.
See this question for an example.
I'm trying to fiddle with Foursquare's HeapAudit, and am attempting to set it up using IntelliJ IDEA. I have managed to get it to build just fine, using the dependencies from the pom.xml.
However, when I actually try to run the JUnit tests, basically all of them fail. I'm guessing this is because using HeapAudit requires the JVM to be started with it as a -javaagent, according to the github:
$ java -javaagent:heapaudit.jar MyTest
Presumably the tests would pass if I put this line in, and referenced the heapaudit.jar i downloaded/built earlier. However, it seems to me that if I make changes the the source, I'm gonna need to re-package this silly .jar file in order to see if it works.
Is there any way of running the tests with a -javaagent without going through the whole rigmarole of compile -> package-into-jar every testing cycle? Perhaps getting IntelliJ to attached the newly-compiled .class files as a -javaagent before running the tests?
1) Have a jar just with a META-INF/MANIFEST.MF
The manifest must be properly configured with Premain-Class and other attributes. The jar doesn't need any other files. Use this jar with the -javaagent. Provided that the agent classes are in the classpath, the agent will start normally.
This might fail when using maven-surefire-plugin with forkMode=never because by default the application classes are loaded in a child ClassLoader.
Works fine with Eclipse and Intellij.
If doing this, double check the manifest syntax (once I spent a long time to figure out that a package name was wrong).
2) Use ea-agent-loader
It will allow you to load the agent (any agent) in runtime (it uses VM.attach()). However the VM.attach() sometimes disrupts debugging and breakpoints might fail to trigger.
It will have the same issues with the surefire in forkMode=never
3) Load the agent in runtime.
Write your on code to load the agent in runtime. And call it from your #BeforeClass You will still need a jar (which you can generate in runtime if you want).
Just you need to call this (only once):
AgentLoader.loadAgentClass(YourAgentClass.class.getName());
We have a jar that we lost the source code to. I decompiled the jar and created new source from it. I want to then verify that the source code and the old jar have the same behavior. I am writing unit tests to do the verification the problem is that they both have same namespace / class name so I do not know how to disambiguate the old jar and the new source code. What can I do or is it impossible?
You need to only have one version on the class path at once to guarantee that you are running that version of the code. Develop your unit test separate from the code so you can drop in either version.
Give the new source a temporary namespace for testing purposes. Then instead of import, you can refer your new classes as:
com.yourfirm.test.packagename.TheClassName
the old ones can be simply imported and refered to as TheClassName. This way you can tell by looking at your test cases which is which.
Or simply run the tests with -cp oldpackage.jar and then -cp newpackage.jar.
It's possible, but you have to mess around with class loading. Instead of putting either of the jars on the classpath, you'll need to load them at runtime. Check out JCL for a library to allow you to do this. (Disclaimer: I have never used JCL.)
Basically, each test would have to load the class from the old JAR, grab the results of the method you're testing, then unload that JAR, load up the new one, run the same method against the new version, and compare the results.
I'd change which classes are being tested at runtime with the classpath. This approach would be less error-prone in terms of ensuring that you're running the same test code against both binaries. Otherwise you introduce more complexity around whether the tests are correct.
It sounds like you are trying to execute the tests against both jars at the same time. I don't know of a way to disambiguate the old/new jars if they are both in the classpath.
If your unit tests output results to stdout/stderr, you could run the tests against the original jar and save the results. Then run the tests against the new jar and save the results in a separate file. Then diff the files.
Another approach would be to refactor the new source code so that it has a unique namespace. You could then test against both jars at the same time, but it could be a lot of work to make existing programs use the new jar.
If you run your tests via ant (Junit-task), you can control the ant classpath seperately for both runs (once via jar, once via fileset of classes).