kingpin icon indicating copy to clipboard operation
kingpin copied to clipboard

Unexpected "doubling" behavior when trying to test output

Open peterbourgon opened this issue 4 years ago • 1 comments

I am trying to write some unit tests for my kingpin.Application, to test things like help output. To do that, I build the application the same as I would in my real program, and redirect output to a buffer. I also apparently have to tell the app not to terminate the program (the test) whenever it encounters an error. But when I do all of these things, I notice that the Terminate callback is called multiple times (though only when I have a subcommand) and the expected output is duplicated.

Here is a small reproducible test case.

package main

import (
	"bytes"
	"fmt"

	"gopkg.in/alecthomas/kingpin.v2"
)

func main() {
	app := kingpin.New("test", "Test application.")
	_ = app.Command("subcommand", "A subcommand.")
	var buf bytes.Buffer
	app.Writer(&buf)
	app.Terminate(func(exitcode int) { fmt.Printf("terminate(%d)\n", exitcode) })
	_, err := app.Parse([]string{"--help"})
	fmt.Printf("Parse error: %v\n", err)
	fmt.Printf("%s\n", buf.String())
}

Expected output:

terminate(0)
Parse error: command not specified
usage: test [<flags>] <command> [<args> ...]

Test application.

Flags:
  --help  Show context-sensitive help (also try --help-long and --help-man).

Commands:
  help [<command>...]
    Show help.

  subcommand
    A subcommand.

Actual output:

terminate(0)
terminate(0)
Parse error: command not specified
usage: test [<flags>] <command> [<args> ...]

Test application.

Flags:
  --help  Show context-sensitive help (also try --help-long and --help-man).

Commands:
  help [<command>...]
    Show help.

  subcommand
    A subcommand.


usage: test [<flags>] <command> [<args> ...]

Test application.

Flags:
  --help  Show context-sensitive help (also try --help-long and --help-man).

Commands:
  help [<command>...]
    Show help.

  subcommand
    A subcommand.

If there is a better way to do what I want to do, I'm all ears. But for now, this looks like a bug.

peterbourgon avatar Sep 18 '19 19:09 peterbourgon

For me help this code

usage := ""
usageBuffer := bytes.Buffer{}
app := kingpin.New("test", "")
app.Terminate(func(int) {
   usage = usageBuffer.String()
   usageBuffer.Reset()
})
app.UsageWriter(&usageBuffer)

...

fmt.Println(usage)

IvanLutokhin avatar Feb 04 '22 07:02 IvanLutokhin