Unit testing 如何对用golang编写的promptui包进行单元测试?

Unit testing 如何对用golang编写的promptui包进行单元测试?,unit-testing,go,command-prompt,Unit Testing,Go,Command Prompt,我是golang的新手,在我的一个项目中使用了一个名为promptui()的交互式提示符。我已经为这个项目编写了几个单元测试,但是我正在努力解决如何对这个需要输入的特定包进行单元测试的问题 例如,我将如何测试以下代码行(封装在函数中): 我认为我需要以某种方式模拟stdin,但无法找出在测试中实现这一点的最佳方法。无论出于何种原因,他们都不会导出其stdin接口(),因此您无法模拟它,但您可以直接模拟os.stdin,并用测试所需的任何内容对其进行预填充。虽然我同意@Adrian的说法,但它有自

我是golang的新手,在我的一个项目中使用了一个名为promptui()的交互式提示符。我已经为这个项目编写了几个单元测试,但是我正在努力解决如何对这个需要输入的特定包进行单元测试的问题

例如,我将如何测试以下代码行(封装在函数中):


我认为我需要以某种方式模拟stdin,但无法找出在测试中实现这一点的最佳方法。

无论出于何种原因,他们都不会导出其
stdin
接口(),因此您无法模拟它,但您可以直接模拟
os.stdin
,并用测试所需的任何内容对其进行预填充。虽然我同意@Adrian的说法,但它有自己的测试,所以这应该是没有必要的

从源代码中提取并重构/简化:

通过这种方式重构,它可以用于任何从
os.Stdin
读取并需要特定字符串的函数

游乐场连接:


无论出于何种原因,它们都不会导出其
stdin
接口(),因此您无法模拟它,但您可以直接模拟
os.stdin
,并用测试所需的任何东西预先填充它。虽然我同意@Adrian的说法,但它有自己的测试,所以这应该是没有必要的

从源代码中提取并重构/简化:

通过这种方式重构,它可以用于任何从
os.Stdin
读取并需要特定字符串的函数

游乐场连接:


您不应该尝试测试
promptui
,因为它应该由作者测试

您可以测试的内容:

  • 创建
    promptui.Prompt时发送正确的参数
  • 您可以在代码中使用
    promptui.Prompt
  • 正确处理
    promptui.Prompt
    结果
  • 如您所见,所有这些测试都无法验证
    promptui.Prompt
    是否在内部正常工作

    测试2和测试3可以结合使用。您需要针对mock运行代码,如果得到正确的结果,您可以相信#2和#3都是正确的

    创建模拟:

    type Runner interface {
        Run() (int, string, error)
    }
    
    type promptMock struct {
        // t is not required for this test, but it is would be helpful to assert input parameters if we have it in Run()
        t *testing.T
    }
    
    func (p promptMock) Run() (int, string, error) {
        // return expected result
        return 1, "", nil
    }
    
    您将需要单独的模拟来测试错误流

    更新代码以注入模拟:

    func setEmail(runner Runner) string {
        email, err := runner.Run()
        if err != nil {
          color.red("failed getting email")
          os.exit(3)
        }
        return email
    }
    
    现在它是可测试的

    创建创建
    提示的函数

    func getRunner() promptui.Prompt {
      return promptui.Prompt{Label: "Input your Email",
         Validate: emailValidations,
      }
    } 
    
    编写简单的断言测试来验证我们是否创建了正确的结构


    唯一未测试的行将是
    setEmail(getRunner())
    ,但它很简单,可以被其他类型的测试覆盖。

    您不应该尝试测试
    promptui
    ,因为它的作者预计会对它进行测试

    您可以测试的内容:

  • 创建
    promptui.Prompt时发送正确的参数
  • 您可以在代码中使用
    promptui.Prompt
  • 正确处理
    promptui.Prompt
    结果
  • 如您所见,所有这些测试都无法验证
    promptui.Prompt
    是否在内部正常工作

    测试2和测试3可以结合使用。您需要针对mock运行代码,如果得到正确的结果,您可以相信#2和#3都是正确的

    创建模拟:

    type Runner interface {
        Run() (int, string, error)
    }
    
    type promptMock struct {
        // t is not required for this test, but it is would be helpful to assert input parameters if we have it in Run()
        t *testing.T
    }
    
    func (p promptMock) Run() (int, string, error) {
        // return expected result
        return 1, "", nil
    }
    
    您将需要单独的模拟来测试错误流

    更新代码以注入模拟:

    func setEmail(runner Runner) string {
        email, err := runner.Run()
        if err != nil {
          color.red("failed getting email")
          os.exit(3)
        }
        return email
    }
    
    现在它是可测试的

    创建创建
    提示的函数

    func getRunner() promptui.Prompt {
      return promptui.Prompt{Label: "Input your Email",
         Validate: emailValidations,
      }
    } 
    
    编写简单的断言测试来验证我们是否创建了正确的结构


    唯一未测试的行是
    setEmail(getRunner())
    ,但它很简单,可以被其他类型的测试覆盖。

    为什么要对外部包进行单元测试?它应该已经有了自己的测试。我想测试我使用该软件包的函数。使用它的函数本身不做任何事情,单元测试它不提供任何值。它返回电子邮件字符串。该函数在整个过程中使用了几次。我想我可以在整个过程中重复使用相同的promptui代码块,但我认为这不符合枯燥的最佳实践。我同意测试调用
    promptui
    的代码是有价值的。测试创建一个
    安全网
    ,减少回归错误。你永远不知道将来如何重构/扩展代码。为什么要对外部包进行单元测试?它应该已经有了自己的测试。我想测试我使用该软件包的函数。使用它的函数本身不做任何事情,单元测试它不提供任何值。它返回电子邮件字符串。该函数在整个过程中使用了几次。我想我可以在整个过程中重复使用相同的promptui代码块,但我认为这不符合枯燥的最佳实践。我同意测试调用
    promptui
    的代码是有价值的。测试创建一个
    安全网
    ,减少回归错误。你永远不知道将来如何重构/扩展代码。谢谢你的帮助。谢谢你的帮助。谢谢你的帮助。谢谢你的帮助。谢谢你的帮助。