草庐IT

unit-testing - 测试非不透明错误值

coder 2023-06-28 原文

在 Go 中是否有比较非不透明错误值的最佳实践?

大多数代码库似乎将错误视为不透明的(操作成功或失败,无法看到有关导致错误的内部细节)。

这使得编写单元测试变得容易,因为您需要做的就是根据预期错误断言实际错误。除此之外,我见过人们做的最多的事情就是比较错误字符串以确保它至少包含一些关键信息。例如:

if err == nil || !strings.Contains(err.Error(), "not found in the Raft configuration") {
  t.Fatalf("err: %v", err)
}

但是对于需要额外错误信息的情况(比如在表单验证中,您需要指定无效的字段名称、值、错误代码以及可能的一些嵌套错误),您会怎么做?

我不能简单地执行 reflect.DeepEqual(),因为错误将包含一个唯一的堆栈跟踪,这将使比较每次都失败。此外,嵌套错误会使测试逻辑更加复杂,您将需要各种容易出错的逻辑(循环、递归)来比较所需的字段。是否有测试这种性质的错误的标准方法?

最佳答案

虽然这可能无法回答您有关检查未正确完成的错误的问题,但这里至少是一个示例,说明如何以正确的方式创建和使用错误。

标准库包中通常做的是将错误创建为导出变量,然后可以抛出这些错误并进行比较。这是一个示例……无论它多么缺乏想象力。

https://play.golang.org/p/JlpguFn2NX

package main

import (
    "errors"
    "fmt"
)

var ErrBadIdea = errors.New("that was dumb")
var ErrNoValue = errors.New("not a real value")

func DoSomething(i int) error {
    if i == 0 {
        return ErrNoValue
    }
    if i < 0 {
        return ErrBadIdea
    }
    // does something that doesn't like negative or zero values
    return nil
}

func main() {
    err := DoSomething(-1)
    fmt.Println(err == ErrBadIdea, err)
    err = DoSomething(0)
    fmt.Println(err == ErrNoValue, err)
}

标准库的 database/sql 包就是一个很好的例子。

https://godoc.org/database/sql#pkg-variables

这些变量存在所以你可以这样测试

if err == sql.ErrNoRows { // these are not the rows you are looking for }

越来越好!

因为error 是一个接口(interface),所以您所要做的就是实现它。这只需要您有一个 func Error() string。请参阅以下示例并惊叹于 interface 的强大功能。

https://play.golang.org/p/3RFrxKGkdm

另请阅读以下有关错误的博客。

https://blog.golang.org/error-handling-and-go

关于unit-testing - 测试非不透明错误值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43214776/

有关unit-testing - 测试非不透明错误值的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  4. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  5. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  6. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  7. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  8. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  9. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  10. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

随机推荐