Skip to content

Extract CLI logic from TestNG core - #2612

Closed
juherr wants to merge 9 commits into
testng-team:masterfrom
juherr:feature/picocli
Closed

Extract CLI logic from TestNG core#2612
juherr wants to merge 9 commits into
testng-team:masterfrom
juherr:feature/picocli

Conversation

@juherr

@juherr juherr commented Jul 16, 2021

Copy link
Copy Markdown
Member

Did you remember to?

  • Add test case(s)
  • Update CHANGES.txt

https://github.com/remkop/picocli is the new defacto library for CLI.
Even if there is no plan to change the default implementation, JCommander was deeply linked.

The goal of this PR is to remove the strong dependency to JCommander.

@juherr juherr added the Runner: CLI Running TestNG from the command line label Jul 16, 2021
@juherr
juherr requested a review from krmahadevan July 16, 2021 20:42
@krmahadevan

Copy link
Copy Markdown
Member

@juherr - Please give me some more time to go through this implementation (maybe this weekend). I liked this decoupling 👍
I will try to wrap up whatever observations I had by that time.

One thing. Do you think we can start preferring to use Streams and lambdas over regular for loops ?

@krmahadevan

Copy link
Copy Markdown
Member

@juherr - I tried checking out your branch and then running the tests via ./gradlew clean test. I see a lot of test failures.
I also tried running a sample test case from within IntelliJ, I am seeing

Exception in thread "main" java.lang.InstantiationError: org.testng.CommandLineArgs
	at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:106)

Process finished with exit code 1

Please let me know if I am doing anything incorrectly here.

@juherr
juherr marked this pull request as draft July 18, 2021 11:05
@juherr

juherr commented Jul 18, 2021

Copy link
Copy Markdown
Member Author

@krmahadevan Thanks for the feedback. I moved it to draft because I didn't check tests yet.

If the move looks good enough for you, I will finish it asap.

@krmahadevan

Copy link
Copy Markdown
Member

@juherr - Sure. I am fine with this change. Please help take it forward.

juherr added a commit to juherr/testng that referenced this pull request Jul 29, 2026
testng-core depended on org.jcommander:jcommander in `api` scope, so every
consumer got the parsing library whether or not it drove TestNG from a command
line. The coupling ran deep: CommandLineArgs was a @Parameter-annotated POJO,
TestNG held a static JCommander field, and TestNG.configure(CommandLineArgs)
mixed applying configuration with CLI-only string-to-object conversion.

The front end now lives in two new modules:

  testng-cli         CliOptions, CliConfigurer, AbstractCliRunner - no parser
  testng-jcommander  the JCommander implementation, plus Converter

testng-core keeps a minimal ServiceLoader SPI, ITestNGCliRunner, so that
"java -cp testng.jar org.testng.TestNG suite.xml" is unchanged: both modules are
bundled into the merged jar. Implementations never terminate the JVM - an
unusable command line comes back as a TestNGException, and only TestNG.main
turns it into a message, a usage banner and exit code 1.

Backward compatibility for 7.x is kept through frozen @deprecated shims:
CommandLineArgs (annotations stripped), TestNG.configure(CommandLineArgs),
TestNG.validateCommandLineParameters, TestNG.main and TestNG.privateMain.
TestNG.configure(Map), the method Maven Surefire calls, still builds a
CommandLineArgs, so removing that class depends on Surefire moving first.
CliConfigurerParityTest compares the state both paths produce, field by field,
because nothing else keeps the frozen copy in sync with the live one.

testng-test-kit becomes the shared test-fixture library, so the 22 tests whose
subject is the command line could move to testng-jcommander. The 243 classes
extending SimpleBaseTest are unaffected.

The two modules are deliberately not published on their own, and are kept out of
the BOM for the same reason: that would ship org.testng.cli.* and its service
registration in two artifacts at once. It is a packaging change for the next
major, tracked in testng-team#3301.

Supersedes testng-team#2612.
juherr added a commit to juherr/testng that referenced this pull request Jul 29, 2026
testng-core depended on org.jcommander:jcommander in `api` scope, so every
consumer got the parsing library whether or not it drove TestNG from a command
line. The coupling ran deep: CommandLineArgs was a @Parameter-annotated POJO,
TestNG held a static JCommander field, and TestNG.configure(CommandLineArgs)
mixed applying configuration with CLI-only string-to-object conversion.

The front end now lives in two new modules:

  testng-cli         CliOptions, CliConfigurer, AbstractCliRunner - no parser
  testng-jcommander  the JCommander implementation, plus Converter

testng-core keeps a minimal ServiceLoader SPI, ITestNGCliRunner, so that
"java -cp testng.jar org.testng.TestNG suite.xml" is unchanged: both modules are
bundled into the merged jar. Implementations never terminate the JVM - an
unusable command line comes back as a TestNGException, and only TestNG.main
turns it into a message, a usage banner and exit code 1.

Backward compatibility for 7.x is kept through frozen @deprecated shims:
CommandLineArgs (annotations stripped), TestNG.configure(CommandLineArgs),
TestNG.validateCommandLineParameters, TestNG.main and TestNG.privateMain.
TestNG.configure(Map), the method Maven Surefire calls, still builds a
CommandLineArgs, so removing that class depends on Surefire moving first.
CliConfigurerParityTest compares the state both paths produce, field by field,
because nothing else keeps the frozen copy in sync with the live one.

testng-test-kit becomes the shared test-fixture library, so the 22 tests whose
subject is the command line could move to testng-jcommander. The 243 classes
extending SimpleBaseTest are unaffected.

The two modules are deliberately not published on their own, and are kept out of
the BOM for the same reason: that would ship org.testng.cli.* and its service
registration in two artifacts at once. It is a packaging change for the next
major, tracked in testng-team#3301.

Supersedes testng-team#2612.
juherr added a commit to juherr/testng that referenced this pull request Jul 29, 2026
testng-core depended on org.jcommander:jcommander in `api` scope, so every
consumer got the parsing library whether or not it drove TestNG from a command
line. The coupling ran deep: CommandLineArgs was a @Parameter-annotated POJO,
TestNG held a static JCommander field, and TestNG.configure(CommandLineArgs)
mixed applying configuration with CLI-only string-to-object conversion.

The front end now lives in two new modules:

  testng-cli         CliOptions, CliConfigurer, AbstractCliRunner - no parser
  testng-jcommander  the JCommander implementation, plus Converter

testng-core keeps a minimal ServiceLoader SPI, ITestNGCliRunner, so that
"java -cp testng.jar org.testng.TestNG suite.xml" is unchanged: both modules are
bundled into the merged jar. Implementations never terminate the JVM - an
unusable command line comes back as a TestNGException, and only TestNG.main
turns it into a message, a usage banner and exit code 1.

TestNG.setThreadCount now raises a TestNGException below 1 instead of printing
the usage banner and calling System.exit(1), so that no library setter can kill
an embedder's JVM. The command line output is unchanged: TestNG.main turns that
exception into the same message and the same exit code.

Backward compatibility for 7.x is kept through frozen @deprecated shims:
CommandLineArgs (annotations stripped), TestNG.configure(CommandLineArgs),
TestNG.validateCommandLineParameters, TestNG.main and TestNG.privateMain.
TestNG.configure(Map), the method Maven Surefire calls, still builds a
CommandLineArgs, so removing that class depends on Surefire moving first.
CliConfigurerParityTest compares the state both paths produce, field by field,
because nothing else keeps the frozen copy in sync with the live one.

testng-test-kit becomes the shared test-fixture library, so the 22 tests whose
subject is the command line could move to testng-jcommander. The 243 classes
extending SimpleBaseTest are unaffected.

The two modules are deliberately not published on their own, and are kept out of
the BOM for the same reason: that would ship org.testng.cli.* and its service
registration in two artifacts at once. It is a packaging change for the next
major, tracked in testng-team#3301.

Supersedes testng-team#2612.
@juherr

juherr commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

superseed by #3307

@juherr juherr closed this Jul 29, 2026
juherr added a commit to juherr/testng that referenced this pull request Jul 29, 2026
testng-core depended on org.jcommander:jcommander in `api` scope, so every
consumer got the parsing library whether or not it drove TestNG from a command
line. The coupling ran deep: CommandLineArgs was a @Parameter-annotated POJO,
TestNG held a static JCommander field, and TestNG.configure(CommandLineArgs)
mixed applying configuration with CLI-only string-to-object conversion.

The front end now lives in two new modules:

  testng-cli         CliOptions, CliConfigurer, AbstractCliRunner - no parser
  testng-jcommander  the JCommander implementation, plus Converter

testng-core keeps a minimal ServiceLoader SPI, ITestNGCliRunner, so that
"java -cp testng.jar org.testng.TestNG suite.xml" is unchanged: both modules are
bundled into the merged jar. Implementations never terminate the JVM - an
unusable command line comes back as a TestNGException, and only TestNG.main
turns it into a message, a usage banner and exit code 1.

TestNG.setThreadCount now raises a TestNGException below 1 instead of printing
the usage banner and calling System.exit(1), so that no library setter can kill
an embedder's JVM. The command line output is unchanged: TestNG.main turns that
exception into the same message and the same exit code.

Backward compatibility for 7.x is kept through frozen @deprecated shims:
CommandLineArgs (annotations stripped), TestNG.configure(CommandLineArgs),
TestNG.validateCommandLineParameters, TestNG.main and TestNG.privateMain.
TestNG.configure(Map), the method Maven Surefire calls, still builds a
CommandLineArgs, so removing that class depends on Surefire moving first.
CliConfigurerParityTest compares the state both paths produce, field by field,
because nothing else keeps the frozen copy in sync with the live one.

testng-test-kit becomes the shared test-fixture library, so the 22 tests whose
subject is the command line could move to testng-jcommander. The 243 classes
extending SimpleBaseTest are unaffected.

The two modules are deliberately not published on their own, and are kept out of
the BOM for the same reason: that would ship org.testng.cli.* and its service
registration in two artifacts at once. It is a packaging change for the next
major, tracked in testng-team#3301.

Supersedes testng-team#2612.
juherr added a commit to juherr/testng that referenced this pull request Jul 30, 2026
testng-core depended on org.jcommander:jcommander in `api` scope, so every
consumer got the parsing library whether or not it drove TestNG from a command
line. The coupling ran deep: CommandLineArgs was a @Parameter-annotated POJO,
TestNG held a static JCommander field, and TestNG.configure(CommandLineArgs)
mixed applying configuration with CLI-only string-to-object conversion.

The front end now lives in two new modules:

  testng-cli         CliOptions, CliConfigurer, AbstractCliRunner - no parser
  testng-jcommander  the JCommander implementation, plus Converter

testng-core keeps a minimal ServiceLoader SPI, ITestNGCliRunner, so that
"java -cp testng.jar org.testng.TestNG suite.xml" is unchanged: both modules are
bundled into the merged jar. Implementations never terminate the JVM - an
unusable command line comes back as a TestNGException, and only TestNG.main
turns it into a message, a usage banner and exit code 1.

TestNG.setThreadCount now raises a TestNGException below 1 instead of printing
the usage banner and calling System.exit(1), so that no library setter can kill
an embedder's JVM. The command line output is unchanged: TestNG.main turns that
exception into the same message and the same exit code.

Backward compatibility for 7.x is kept through frozen @deprecated shims:
CommandLineArgs (annotations stripped), TestNG.configure(CommandLineArgs),
TestNG.validateCommandLineParameters, TestNG.main and TestNG.privateMain.
TestNG.configure(Map), the method Maven Surefire calls, still builds a
CommandLineArgs, so removing that class depends on Surefire moving first.
CliConfigurerParityTest compares the state both paths produce, field by field,
because nothing else keeps the frozen copy in sync with the live one.

testng-test-kit becomes the shared test-fixture library, so the 22 tests whose
subject is the command line could move to testng-jcommander. The 243 classes
extending SimpleBaseTest are unaffected.

The two modules are deliberately not published on their own, and are kept out of
the BOM for the same reason: that would ship org.testng.cli.* and its service
registration in two artifacts at once. It is a packaging change for the next
major, tracked in testng-team#3301.

Supersedes testng-team#2612.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Runner: CLI Running TestNG from the command line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants