Error vs Fatal in tests - go

I am developing a JSON web service using Go-Json-Rest. I am writing tests.
...
recorded = test.RunRequest(t, &api.Handler,
test.MakeSimpleRequest("POST", "http://localhost/api/products",
product))
recorded.CodeIs(201)
recorded.ContentTypeIsJson()
var newProduct Product
err := recorded.DecodeJsonPayload(&newProduct)
if err != nil {
t.Fatal(err)
}
...
I am using Fatal as I am coming from Python world where an assert would immediately stop test case method execution. And this make sense: why trying to decode the data, if it's not JSON?
But recorded.CodeIs(201), recorded.ContentTypeIsJson() and other tests I've seen use Error which doesn't stop test execution.
What should I use in tests? Error or Fatal?

I think you use Error until continuing to run the test can't possibly give you any more information useful in debugging, then you use Fatal. And if you're not sure (like if you're writing a factored-out method like CodeIs to be used in the context of lots of different tests), go for Error, since you're generally not doing harm by continuing to run the test.
By that criteria, it makes sense for you to Fatal at failed JSON decoding after which, as you say, nothing interesting is going to happen. And it's understandable that CodeIs and ContentTypeIsJson use Error because they're methods that are going to be used across different tests.
A different example might better illustrate why to use Error until you know nothing else interesting will happen: say you want to sanity-check several different things about the JSON response, and any subset them could be wrong. (Like, your product API could return price using the wrong type, or it could fail to return empty descriptions when you don't want that, or...) Using Error instead of Fatal for each check means your test will always run them all and report which ones failed.

Related

Checking (value or type) against errors returned by fmt.Errorf

If a piece of code has its own error type as in
var ErrSomethingWentWrong = errors.New("Something went wrong"
I believe in my code I can do this
import github.com/therepo/theproject/thepackage/thatexportstheaboveerror
// code that might return the above error
if err == thatexportstheaboveerror.ErrSomethingWentWrong {
// handle the particular case
}
What happens when the error returned is via fmt.Errorf as in this case?
return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", keys(tried))
How can value (or type or whatever) check/assertion should be performed go-idiomatically?
Is this the only way around it?
if err != nil {
if strings.Contains(err.Error(), "unable to authenticate") {
// handle the particular error
}
}
Since Go version 1.13, the errors package has included the concept of "wrapping" errors. A routine returning a "wrapped" error calls fmt.Errorf using the %w verb in the format, to wrap an inner error into an outer error. An outer error can then be tested to see if it contains a particular inner error.
Prior to that, xerrors provided the same general concept.
Both of these require that whoever produces the error value use the provided wrapping interface. The routine you are asking about—part of https://godoc.org/golang.org/x/crypto/ssh—does not do this. Some older code that doesn't wrap errors provides certain kind of error-testing functions. For instance, when os.Open returns an error, os.IsNotExist will tell you if that error is because the file does not exist.
Unfortunately this particular package has no such test, so you're pretty much stuck with what you've suggested (direct string inspection) if you really want to know, programmatically, that this error came from this particular source.

How can I use dynamic errors while retaining comparability for testing?

In go I often use
func MyFunc(s someInterface) error {
err := OtherFunc(s)
return fmt.Errorf("something wrong: %s", err)
}
So I lose the original error value, because I just take the error string and forge it into a new error. That is what I mean with dynamic errors.
Now consider a test for MyFunc():
func TestMyFunc(t *testing.T) {
s := mockSomeInterface()
testErr := MyFunc(s)
if testErr != interfaceSpecificErrorValue {
t.Errorf("fail")
}
}
What would I use for interfaceSpecificErrorValue (which is specific to someInterface in this example)? Or how could I make this testable?
I understand that I can solve this by defining all my possible errors beforehand and give them a constant value. What I am interested in is if there is another way to achieve this, because I like the hierarchical error messages that you can dynamically build up using fmt.Errorf("...: %s, err). There must be a good way to keep the error hierarchy without losing the original value.
(Comparing the output of the Error() method is a possibility, but not a good one.)
My preliminary answer to this is: In Go currently there is no canonical way to achieve nested errors with comparable error values.
After reading the offical documents and blog posts on error handling again, quite some source code from standard libraries, and finally this proposal: https://github.com/golang/proposal/blob/master/design/go2draft-error-values-overview.md, I decided I will keep my error types simple and static and wait for Go 2 to offer a better way.

Drupal, entity_metadata_wrappers and debugging

For handling entities in Drupal I'm using Entity Metadata Wrappers (the "Drupal way").
It's really easy to start coding and see all the advantages it has... except when you get a fatal error and you are not clear where it comes from.
This is what the database log shows:
EntityMetadataWrapperException: Unknown data property
field_whatever. at EntityStructureWrapper->getPropertyInfo()
(line 335 of
/var/www/html/sites/all/modules/entity/includes/entity.wrapper.inc).
Sadly, many times that "field_whatever" is "nid", "uid" or some very common property, so it's name is spread all over my code, which makes me difficult to get to the origin of the error.
I'm currently doing this:
Write a tiny piece of code and then run to see if something fails.
Using getPropertyInfo when handling entities with "not so common" fields.
Loosing hair.
What is worst is that sometimes the error does not appear when you are coding, but a week later. So it could be anywhere...
Is there any way of handling entity metadata wrapper errors better? Can I get better information in the database log and not just a line? A backtrace maybe?
Thanks.
Well, having the devel module active (just to see the nice krumo message) we can do something like this inside our module:
<?php
set_exception_handler('exception_with_trace');
function exception_with_trace($e)
{
dpm($e->getTrace());
}
That will return the backtrace error of the exception thrown by the entity metadata handler on the next page load (some page in your site where everything is running fine).
Also you can set the exception handler exclusively and more elegant just for some pages or some users with some role... or when some parameter in the url is met, or when in some state of your Drupal site is met (ex. when a bool persistent variable 'exception_with_trace' is true). Even, under certain conditions and control, you can use it in production too.
If the site does not work "at all" you can include it in your settings.php file, but instead of printing the trace, you must write the trace to a file and watch the trace in a different context (not Drupal but some php file).
If exceptions are too long and are causing memory problems then getting the trace as string is also possible. See http://php.net/manual/es/exception.gettraceasstring.php
Hope that helps.

Raising an an exception: string vs custom class

Is there any advantage to do:
ApiTokenExpired = Class.new(StandardError)
...
raise ApiTokenExpired if response.errorCode == 429
over this lazier alternative:
raise 'api token expired' if response.errorCode == 429
considering that this error detection happens only once in the code?
There is an important advantage of custom errors like ApiTokenExpired if you have to handle the error in an specific way somewhere in the call stack.
begin
# ...
rescue ApiTokenExpired => error
# handle the specific error
rescue => error
# default error handling
end
IMO the decision to create custom errors doesn't depend on the size of the project or future maintenance.
Since custom error classes cause an extra effort I don't use it by default. When a special error handling is needed then an error class should be introduced.
With the first one, you can selectively rescue that error by the class when that code is embedded in larger software. You can still do that with the second one using pattern match with the error message string, but in general, you might alter the message format over time due to refactoring (as opposed to unlikelihood of changing the exception class with your first form), and there can also be different exceptions that have a similar message string, both of which can break pattern matching. When you consider future maintenance, the first one is better.
It does if your app is designed to have error handling or plan to in the future(I mean, any successfull system will want that one day, right?), the only thing you can do with a string is read it in a log or display it in an error message, with types you can code all sorts of things in a decoupled fashion.
For example, ApiTokenExpired could maybe be handled with "try again" response since it's an external problem or be handled by the steps necessary to renew the API Token(and if you used a Typed Exception, you can plug it in later!), maybe you want all errors that are considered SEVERE or UNEXPECTED to send the system administrator an e-mail and also store statistics on the frequency of the error, typed exceptions allows you to code in anything you want in terms of what to do when your system is misbehaving.

Ruby on Rails Exceptions

I am a junior rails developer and was advised to use Class.find(id) to query the database instead of Class.find_by_id(id) which I previously had. The reason I was told is because the former would raise an exception while the latter would return nil. I realize this happens but I am wondering what the high level conceptual logic is for doing it this way. Why do I want the exception? Is this a rails standard where I would always prefer a method that returns an exception as opposed to nil?
You typically want the exception because you're typically doing Foo.find(id) based on data input coming from the user, such as clicking on a link.
For example, you show the user a list of items. There are links like this:
http://example.com/items/100
http://example.com/items/101
http://example.com/items/102
The user clicks the first link, and expects to see item 100.
Your code does this:
Item.find(100)
You expect to find the item, because app created the item link. You'd be surprised if the item didn't exist.
(Corner case surprises are possible: perhaps the item was deleted, or perhaps a hacker is sending in missing ids, etc. Using exceptions helps you handle this as an exceptional circumstance.)
Exceptions are preferred to nil for this, because you want the code to fail immediately so you don't accidentally send the nil on to some other method.
Ruby nil objects can be confusing because they evaluate to falsey and also because nil.id == 4 because of how Ruby uses C. Error messages show up like "Warning: Object#id will be deprecated" or "undefined method for 4:Fixnum".
Nils are problematic as a return type in Ruby in general. There's a great (paid) screencast by Gary Bernhardt that explains why you want to avoid returning nil from methods, but in a nutshell: when a method returns nil, and that nil gets passed up through a chain of method calls and something goes wrong somewhere, it can be extremely difficult to figure out where the actual problem occurred.
Say, for example, you have something like this:
foo_model = MyModel.find_by_name('foo')
# some more lines of code
do_something(foo_model)
and a method:
def do_something(model)
# some stuff stuff
some_other_method(model)
end
Now, if MyModel.find_by_name('foo') returns nil, that nil will be carried along without any errors until it actually has to do something. Say, in some_other_method, you actually try to call something on model, say model.save, you will get an error:
undefined method 'save' for nil:NilClass (NoMethodError)
The trace will carry you back up the method calls, but it will not mention the line that was actually problematic, where you assign MyModel.find_by_name('foo') (which evaluates to nil) to foo_model.
You can imagine that in a real application, the code can be much more complex, and returning nil can make it much more difficult to figure out the source of an error.
An exception, in contrast, tells you immediately where the problem is, and the trace will go back to the line where it occurred. That's one reason (there are others, I imagine) why in general, returning nil is not a good idea.
Hope that helps.

Resources