Writing Tests for Return Type

Hi

I have been following along with this course Learn Go with Tests. I like the concept of TDD but I am struggling to write my own test.

I am writing a program which will load a query from an ‘.sql’ file, and then run it and store the results as a report.

I am not too sure how I would test this, I have a function that works as per below, but the test does not pass…

The Function

// LoadQuery retrieves .sql file from filesystem
func LoadQuery() {
	// Load Query from file
	content, err := ioutil.ReadFile("query.sql")
	if err != nil {
		log.Fatal("File not found")
	}
	// Convert Query to String
	query := string(content[:])
	return query
}

My test

func TestLoadQuery(t *testing.T) {

	t.Run("load sql from file", func(t *testing.T) {

		if LoadQuery() != string {
			t.Error("Expected string")
		}
	})
}

Does this compile for you? You’re returning a string from LoadQuery(), but not specifying a return parameter - this should fail with a “too many arguments to return” error at compile time.

In addition, if you do change LoadQuery() to return a string, the test would be redundant. But even if you did want to test if a variable was of a certain type (maybe LoadQuery return as interface{}, for example?), you wouldn’t test it like x != string. Rough example: https://play.golang.org/p/aGvCH8OkrWW

Correct, this didn’t compile until I added a return type of string.

Can you elaborate as to why the test would be redundant? Are tests not always necessary?

To write a test for this requirement, reading sql from a file into a string to be sent to the database query client… the problem I have is that my query itself that generates the report is thousands of lines long. This is an issue because thus far I have seen tests written that use back ticks select * from table for the successful test case.

Having said that maybe I can use a pattern matching expression so the test case would be,

got := LoadQuery()
want := `%select%from%`

if got != want {
t.Error("file not sql")
}

Thanks for your response, very grateful for any further input that will contribute to my understanding of testing in Go :smiley:

This particular test would be redundant if you specify a return type of string and then test that the returned variable is of type string - the compiler will guarantee that the return type will always be string in this case. The application will not compile unless you’re returning a string in that function, so the test isn’t really testing anything. In your SQL query example, a more useful test might be that the result is not an empty string, for example (if you always expect to return a SQL query), or that the SQL query string returned is always a valid query for your purposes (similar to the second example you just posted I guess). I hope that makes sense, let me know if not and I can try to explain it another way :slight_smile:

1 Like

Adding my final solution. Further feedback is welcome but I am content that my question has been answered.

Firstly my code:

package main
import (
	"fmt"
	"io/ioutil"
	"log"

)

var err error

func main() {
	fmt.Println(LoadQuery())
}

// LoadQuery retrieves .sql file from filesystem
func LoadQuery() string {
	// Load Query from file
	content, err := ioutil.ReadFile("code_checker.sql")
	if err != nil {
		log.Fatal("File not found")
	}
	// Convert Query to String
	query := string(content[:])
	return query
}

When I remove the byte to string line and run the test I get this error.

c:\dev\go\src\###\reporter.go:53:2: cannot use content (type []byte) as type string in return argument
FAIL	### [build failed]
Error: Tests failed.

Otherwise with string conversion

2018/08/21 14:15:46 File not found
FAIL		0.200s
Error: Tests failed.

And my test:

package main

import (
	"fmt"
	"testing"
)

func TestLoadQuery(t *testing.T) {

	t.Run("load sql from file", func(t *testing.T) {
		// Test fails if either no file present or not string returned.
		if len(LoadQuery()) > 0 {
			fmt.Println("Empty String")
		}
	})
}

Ways this test could be improved I guess include… understanding how to mock a file for the test. Changing the test text to be more idiomatic, maybe the name for this test should be “load string from file” as this is what we are actually doing.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.