Class RealJenkinsRule
- java.lang.Object
-
- org.jvnet.hudson.test.RealJenkinsRule
-
- All Implemented Interfaces:
org.junit.rules.TestRule
public final class RealJenkinsRule extends Object implements org.junit.rules.TestRule
LikeJenkinsSessionRulebut running Jenkins in a more realistic environment.Though Jenkins is run in a separate JVM using Winstone (
java -jar jenkins.war), you can still do “whitebox” testing: directly calling Java API methods, starting fromJenkinsRuleor not. This is because the test code gets sent to the remote JVM and loaded and run there. (Thus when using Maven, there are at least three JVMs involved: Maven itself; the Surefire booter with your top-level test code; and the Jenkins controller with test bodies.) Just as withJenkinsRule, all plugins found in the test classpath will be enabled, but with more realistic behavior: class loaders in a graph,pluginFirstClassLoaderandmaskClasses, etc.“Compile-on-save” style development works for classes and resources in the current plugin: with a suitable IDE, you can edit a source file, have it be sent to
target/classes/, and rerun a test without needing to go through a full Maven build cycle. This is becausetarget/test-classes/the.hplis used to load unpacked plugin resources.Like
JenkinsRule, the controller is started in “development mode”: the setup wizard is suppressed, the update center is not checked, etc.Known limitations:
- Execution is a bit slower due to the overhead of launching a new JVM; and class loading overhead cannot be shared between test cases. More memory is needed.
- Remote thunks must be serializable. If they need data from the test JVM, you will need to create a
staticnested class to package that. staticstate cannot be shared between the top-level test code and test bodies (though the compiler will not catch this mistake).- When using a snapshot dep on Jenkins core, you must build
jenkins.warto test core changes (there is no “compile-on-save” support for this). Assumeis not available.TestExtensionis not available.LoggerRuleis not available, however additional loggers can be configured viawithLogger(Class, Level)}.BuildWatcheris not available, but you can useTailLoginstead.
Systems not yet tested:
- Possibly
Timeoutcan be used. - Possibly
ExtensionList.add(Object)can be used as an alternative toTestExtension.
-
-
Nested Class Summary
-
Constructor Summary
Constructors Constructor Description RealJenkinsRule()RealJenkinsRule(RealJenkinsRule source)Links this rule to another, withgetHome()to be initialized by whichever copy starts first.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description RealJenkinsRuleaddPlugins(String... plugins)Add some plugins to the test classpath.org.junit.runners.model.Statementapply(org.junit.runners.model.Statement base, org.junit.runner.Description description)static StringcheckResult(HttpURLConnection conn)RealJenkinsRuleextraEnv(String key, String value)Set an extra environment variable.FilegetHome()Obtains the Jenkins home directory.static List<String>getJacocoAgentOptions()StringgetName()URLgetUrl()Similar toJenkinsRule.getURL().RealJenkinsRuleincludeTestClasspathPlugins(boolean includeTestClasspathPlugins)The intended use case for this is to use the plugins bundled into the warwithWar(File)instead of the plugins in the pom.RealJenkinsRulejavaOptions(String... options)Add some JVM startup options.RealJenkinsRulejenkinsOptions(String... options)Add some Jenkins (including Winstone) startup options.RealJenkinsRuleomitPlugins(String... plugins)Omit some plugins in the test classpath.voidrunRemotely(RealJenkinsRule.Step... steps)Runs one or more steps on the remote system.<T extends Serializable>
TrunRemotely(RealJenkinsRule.Step2<T> s)<A1 extends Serializable,A2 extends Serializable,A3 extends Serializable,A4 extends Serializable>
voidrunRemotely(RealJenkinsRule.StepWithFourArgs<A1,A2,A3,A4> s, A1 arg1, A2 arg2, A3 arg3, A4 arg4)<A1 extends Serializable>
voidrunRemotely(RealJenkinsRule.StepWithOneArg<A1> s, A1 arg1)<R extends Serializable,A1 extends Serializable,A2 extends Serializable,A3 extends Serializable,A4 extends Serializable>
RrunRemotely(RealJenkinsRule.StepWithReturnAndFourArgs<R,A1,A2,A3,A4> s, A1 arg1, A2 arg2, A3 arg3, A4 arg4)<R extends Serializable,A1 extends Serializable>
RrunRemotely(RealJenkinsRule.StepWithReturnAndOneArg<R,A1> s, A1 arg1)<R extends Serializable,A1 extends Serializable,A2 extends Serializable,A3 extends Serializable>
RrunRemotely(RealJenkinsRule.StepWithReturnAndThreeArgs<R,A1,A2,A3> s, A1 arg1, A2 arg2, A3 arg3)<R extends Serializable,A1 extends Serializable,A2 extends Serializable>
RrunRemotely(RealJenkinsRule.StepWithReturnAndTwoArgs<R,A1,A2> s, A1 arg1, A2 arg2)<A1 extends Serializable,A2 extends Serializable,A3 extends Serializable>
voidrunRemotely(RealJenkinsRule.StepWithThreeArgs<A1,A2,A3> s, A1 arg1, A2 arg2, A3 arg3)<A1 extends Serializable,A2 extends Serializable>
voidrunRemotely(RealJenkinsRule.StepWithTwoArgs<A1,A2> s, A1 arg1, A2 arg2)voidstartJenkins()voidstopJenkins()Stops Jenkins and releases any system resources associated with it.voidthen(RealJenkinsRule.Step... steps)Run one Jenkins session, send one or more test thunks, and shut down.<T extends Serializable>
Tthen(RealJenkinsRule.Step2<T> s)Run one Jenkins session, send a test thunk, and shut down.RealJenkinsRulewithColor(PrefixedOutputStream.AnsiColor color)Applies ANSI coloration to log lines produced by this instance, complementingwithName(java.lang.String).RealJenkinsRulewithDebugPort(int debugPort)Allows usage of a static debug port instead of a random one.RealJenkinsRulewithDebugServer(boolean debugServer)Allows to use debug in server mode or client mode.RealJenkinsRulewithDebugSuspend(boolean debugSuspend)Whether to suspend the controller VM on startup until debugger is connected.RealJenkinsRulewithHost(String host)Sets a custom host name for the Jenkins root URL.RealJenkinsRulewithHttpListenAddress(String httpListenAddress)Provides a custom interface to listen to.RealJenkinsRulewithLogger(Class<?> clazz, Level level)RealJenkinsRulewithLogger(String logger, Level level)RealJenkinsRulewithName(String name)Sets a name for this instance, which will be prefixed to log messages to simplify debugging.RealJenkinsRulewithPackageLogger(Class<?> clazz, Level level)RealJenkinsRulewithPort(int port)Provides a custom fixed port instead of a random one.RealJenkinsRulewithTimeout(int timeout)Adjusts the test timeout.RealJenkinsRulewithWar(File war)Sets a custom WAR file to be used by the rule instead of the one in the path orwar/target/jenkins.warin case of core.
-
-
-
Constructor Detail
-
RealJenkinsRule
public RealJenkinsRule()
-
RealJenkinsRule
public RealJenkinsRule(RealJenkinsRule source)
Links this rule to another, withgetHome()to be initialized by whichever copy starts first. Also copies configuration related to the setup of that directory:includeTestClasspathPlugins(boolean),addPlugins(java.lang.String...), andomitPlugins(java.lang.String...). Other configuration such asjavaOptions(String...)may be applied to both, but that is your choice.
-
-
Method Detail
-
addPlugins
public RealJenkinsRule addPlugins(String... plugins)
Add some plugins to the test classpath.- Parameters:
plugins- Filenames of the plugins to install. These are expected to be absolute test classpath resources, such asplugins/workflow-job.hpifor example.Committing that file to SCM (say,
src/test/resources/sample.jpi) is reasonable for small fake plugins built for this purpose and exercising some bit of code. If you wish to test with larger archives of real plugins, this is possible for example by bindingdependency:copyto theprocess-test-resourcesphase.In most cases you do not need this method. Simply add whatever plugins you are interested in testing against to your POM in
testscope. These, and their transitive dependencies, will be loaded in allRealJenkinsRuletests. This method is useful if only a particular test may load the tested plugin, or if the tested plugin is not available in a repository for use as a test dependency.
-
omitPlugins
public RealJenkinsRule omitPlugins(String... plugins)
Omit some plugins in the test classpath.- Parameters:
plugins- one or more code names, liketoken-macro
-
javaOptions
public RealJenkinsRule javaOptions(String... options)
Add some JVM startup options.- Parameters:
options- one or more options, like-Dorg.jenkinsci.Something.FLAG=true
-
jenkinsOptions
public RealJenkinsRule jenkinsOptions(String... options)
Add some Jenkins (including Winstone) startup options. You probably meant to usejavaOptions(String...).- Parameters:
options- one or more options, like--webroot=/tmp/war --pluginroot=/tmp/plugins
-
extraEnv
public RealJenkinsRule extraEnv(String key, String value)
Set an extra environment variable.- Parameters:
value- null to cancel a previously set variable
-
withTimeout
public RealJenkinsRule withTimeout(int timeout)
Adjusts the test timeout. The timer starts whenstartJenkins()completes andrunRemotely(org.jvnet.hudson.test.RealJenkinsRule.Step...)is ready. The default is currently set to 600 (10m).- Parameters:
timeout- number of seconds before exiting, or zero to disable
-
withHost
public RealJenkinsRule withHost(String host)
Sets a custom host name for the Jenkins root URL.By default, this is just
localhost. But you may wish to set it to something else that resolves to localhost, such assome-id.127.0.0.1.nip.io. This is particularly useful when running multiple copies of Jenkins (and/or other services) in one test case, since browser cookies are sensitive to host but not port and so otherwiseHttpServletRequest.getSession(boolean)might accidentally be shared across otherwise distinct services.Calling this method does not change the fact that Jenkins will be configured to listen only on localhost for security reasons (so others in the same network cannot access your system under test, especially if it lacks authentication).
-
withWar
public RealJenkinsRule withWar(File war)
Sets a custom WAR file to be used by the rule instead of the one in the path orwar/target/jenkins.warin case of core.
-
withLogger
public RealJenkinsRule withLogger(Class<?> clazz, Level level)
-
withPackageLogger
public RealJenkinsRule withPackageLogger(Class<?> clazz, Level level)
-
withLogger
public RealJenkinsRule withLogger(String logger, Level level)
-
withName
public RealJenkinsRule withName(String name)
Sets a name for this instance, which will be prefixed to log messages to simplify debugging.
-
getName
public String getName()
-
withColor
public RealJenkinsRule withColor(PrefixedOutputStream.AnsiColor color)
Applies ANSI coloration to log lines produced by this instance, complementingwithName(java.lang.String). Ignored when on CI.
-
withPort
public RealJenkinsRule withPort(int port)
Provides a custom fixed port instead of a random one.- Parameters:
port- a custom port to use instead of a random one.
-
withHttpListenAddress
public RealJenkinsRule withHttpListenAddress(String httpListenAddress)
Provides a custom interface to listen to.Important: for security reasons this should be overridden only in special scenarios, such as testing inside a Docker container. Otherwise a developer running tests could inadvertently expose a Jenkins service without password protection, allowing remote code execution.
- Parameters:
httpListenAddress- network interface such as0.0.0.0
. Defaults to127.0.0.1
.
-
withDebugPort
public RealJenkinsRule withDebugPort(int debugPort)
Allows usage of a static debug port instead of a random one.This allows to use predefined debug configurations in the IDE.
Typical usage is in a base test class where multiple named controller instances are defined with fixed ports
public RealJenkinsRule cc1 = new RealJenkinsRule().withName("cc1").withDebugPort(4001).withDebugServer(false); public RealJenkinsRule cc2 = new RealJenkinsRule().withName("cc2").withDebugPort(4002).withDebugServer(false);Then have debug configurations in the IDE set for ports- 5005 (test VM) - debugger mode "attach to remote vm"
- 4001 (cc1) - debugger mode "listen to remote vm"
- 4002 (cc2) - debugger mode "listen to remote vm"
This allows for debugger to reconnect in scenarios where restarts of controllers are involved.
- Parameters:
debugPort- the TCP port to use for debugging this Jenkins instance. Between 0 (random) and 65536 (excluded).
-
withDebugServer
public RealJenkinsRule withDebugServer(boolean debugServer)
Allows to use debug in server mode or client mode. Client mode is friendlier to controller restarts.- Parameters:
debugServer- true to use server=y, false to use server=n- See Also:
withDebugPort(int)
-
withDebugSuspend
public RealJenkinsRule withDebugSuspend(boolean debugSuspend)
Whether to suspend the controller VM on startup until debugger is connected. Defaults to false.- Parameters:
debugSuspend- true to suspend the controller VM on startup until debugger is connected.
-
includeTestClasspathPlugins
public RealJenkinsRule includeTestClasspathPlugins(boolean includeTestClasspathPlugins)
The intended use case for this is to use the plugins bundled into the warwithWar(File)instead of the plugins in the pom. A typical scenario for this feature is a test which does not live inside a plugin's src/test/java- Parameters:
includeTestClasspathPlugins- false if plugins from pom should not be used (default true)
-
apply
public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description)- Specified by:
applyin interfaceorg.junit.rules.TestRule
-
then
public void then(RealJenkinsRule.Step... steps) throws Throwable
Run one Jenkins session, send one or more test thunks, and shut down.- Throws:
Throwable
-
then
public <T extends Serializable> T then(RealJenkinsRule.Step2<T> s) throws Throwable
Run one Jenkins session, send a test thunk, and shut down.- Throws:
Throwable
-
getUrl
public URL getUrl() throws MalformedURLException
Similar toJenkinsRule.getURL(). Requires Jenkins to be started before usingstartJenkins().- Throws:
MalformedURLException
-
getHome
public File getHome()
Obtains the Jenkins home directory. Normally it will suffice to useLocalDatato populate files.
-
checkResult
@CheckForNull public static String checkResult(HttpURLConnection conn) throws IOException
- Throws:
IOException
-
stopJenkins
public void stopJenkins() throws ThrowableStops Jenkins and releases any system resources associated with it. If Jenkins is already stopped then invoking this method has no effect.- Throws:
Throwable
-
runRemotely
public void runRemotely(RealJenkinsRule.Step... steps) throws Throwable
Runs one or more steps on the remote system. (Compared to multiple calls, passing a series of steps is slightly more efficient as only one network call is made.)- Throws:
Throwable
-
runRemotely
public <T extends Serializable> T runRemotely(RealJenkinsRule.Step2<T> s) throws Throwable
- Throws:
Throwable
-
runRemotely
public <A1 extends Serializable> void runRemotely(RealJenkinsRule.StepWithOneArg<A1> s, A1 arg1) throws Throwable
- Throws:
Throwable
-
runRemotely
public <A1 extends Serializable,A2 extends Serializable> void runRemotely(RealJenkinsRule.StepWithTwoArgs<A1,A2> s, A1 arg1, A2 arg2) throws Throwable
- Throws:
Throwable
-
runRemotely
public <A1 extends Serializable,A2 extends Serializable,A3 extends Serializable> void runRemotely(RealJenkinsRule.StepWithThreeArgs<A1,A2,A3> s, A1 arg1, A2 arg2, A3 arg3) throws Throwable
- Throws:
Throwable
-
runRemotely
public <A1 extends Serializable,A2 extends Serializable,A3 extends Serializable,A4 extends Serializable> void runRemotely(RealJenkinsRule.StepWithFourArgs<A1,A2,A3,A4> s, A1 arg1, A2 arg2, A3 arg3, A4 arg4) throws Throwable
- Throws:
Throwable
-
runRemotely
public <R extends Serializable,A1 extends Serializable> R runRemotely(RealJenkinsRule.StepWithReturnAndOneArg<R,A1> s, A1 arg1) throws Throwable
- Throws:
Throwable
-
runRemotely
public <R extends Serializable,A1 extends Serializable,A2 extends Serializable> R runRemotely(RealJenkinsRule.StepWithReturnAndTwoArgs<R,A1,A2> s, A1 arg1, A2 arg2) throws Throwable
- Throws:
Throwable
-
runRemotely
public <R extends Serializable,A1 extends Serializable,A2 extends Serializable,A3 extends Serializable> R runRemotely(RealJenkinsRule.StepWithReturnAndThreeArgs<R,A1,A2,A3> s, A1 arg1, A2 arg2, A3 arg3) throws Throwable
- Throws:
Throwable
-
runRemotely
public <R extends Serializable,A1 extends Serializable,A2 extends Serializable,A3 extends Serializable,A4 extends Serializable> R runRemotely(RealJenkinsRule.StepWithReturnAndFourArgs<R,A1,A2,A3,A4> s, A1 arg1, A2 arg2, A3 arg3, A4 arg4) throws Throwable
- Throws:
Throwable
-
-