There are several categories of automated tests in Jenkins, each with different class loading characteristics:
-
Unit tests: Do not start Jenkins and use the test classpath directly.
-
Functional tests (JenkinsRule): Start Jenkins within the same JVM, which may hide some class loading issues.
-
Integration tests (RealJenkinsRule): Start Jenkins in a separate JVM, providing more realistic class loading behavior.
-
Acceptance tests (acceptance-test-harness): Run Jenkins externally and interact via a browser, closely matching production behavior.
These have different levels of fidelity to the class loading behavior of plugin code running in production Jenkins servers.
Unit tests simply pick up the Java classpath (java.class.path) defined by Maven’s test scope.
Acceptance tests run a full Jenkins server and install plugins (including the plugin(s) being tested) using Jenkins’ normal mechanisms.
Since the test does not compile or link against any types defined in the Jenkins runtime (only against the Selenium web driver),
and does not even run in the same JVM as Jenkins, it has no interaction with the class loading of Jenkins.
Thus the class loading behavior of plugins running in an acceptance test can be assumed to be the same as in production.
Class loading in functional tests is intermediate in behavior, but closer to that of unit tests.
Test code does link against Jenkins core and (test-scoped) plugin types,
and everything in the Java classpath is in fact loaded in Java’s application class loader—including plugins in test scope.
This means that certain mistakes in plugin metadata (for example, misuse of pluginFirstClassLoader) may go unnoticed.
(JenkinsRule does start a real Jenkins service, and in some cases other plugins can get installed which were not in the Java classpath.
These get their own class loaders.)
Whenever there is any doubt about whether class loading behavior could affect plugin or core code,
use RealJenkinsRule which launches Jenkins in a separate JVM with the regular class loader hierarchy.