Maciej Wakuła
Maciej Wakuła

Reputation: 133

Testing log.Fatalf in go?

I'd like to achieve 100% test coverage in go code. I am not able to cover the following example - can anyone help me with that?

package example

import (
    "io/ioutil"
    "log"
)

func checkIfReadable(filename string) (string, error) {
    _, err := ioutil.ReadFile(filename)
    if err != nil {
        log.Fatalf("Cannot read the file... how to add coverage test for this line ?!?")
    }
    return "", nil
}

func main() {
    checkIfReadable("dummy.txt")
}

Some dumy test for that:

package example

import (
    "fmt"
    "testing"
)

func TestCheckIfReadable(t *testing.T) {
    someResult, err := checkIfReadable("dummy.txt")
    if len(someResult) > 0 {
        fmt.Println("this will not print")
        t.Fail()
    }
    if err != nil {
        fmt.Println("this will not print")
        t.Fail()
    }
}

func TestMain(t *testing.T) {
...
}

The issue is that log.Fatalf calls os.Exit and go engine dies.

Upvotes: 1

Views: 6497

Answers (2)

adrian
adrian

Reputation: 276

A good way to get 100% test coverage and not fail at the same time is to use recover() to catch the panic that is thrown by log.Fatalf().

Here are the docs for recover. I think it fits your use case nicely.

Upvotes: 0

Grzegorz Żur
Grzegorz Żur

Reputation: 49161

Use log.Print instead of log.Fatal and return the error value that you declared in signature of function checkIfReadable. Or don't the error it and return it to some place that knows better how to handle it.

The function log.Fatal is strictly for reporting your program's final breath.

Calling log.Fatal is a bit worse than calling panic (there is also log.panic), because it does not execute deferred calls. Remember, that overusing panic in Go is considered a bad style.

Upvotes: 9

Related Questions