Usability advice for datastructure library tests

I have an interface for a complex data structure (12 methods), and several structs that implement it, each in its own way (different algorithms).

Does it make sense to create a file with generic test functions, that use only the interface, then call that file for each of my implementing structures ?

Is this a design pattern ? Has anyone seen something similar ?

could you give an example?

Not sure if I understand your question: I have this Graph interface, and multiple implementations of it (undirected graph, tree, adjacency matrix, etc). This interface has 12 methods (String(), Find(), Add(), etc).

Currently my unit tests have (almost) the same logic for all the implementations. This means there are multiple copies of the same test code (one test file for each pakage with very similar tests).

I am brainstormig a way to have a file with tests (that take an interface object as input), and each test file (one test file per package) calls functions from this common test file. Any advice on how I can do this elegantly ?

Hi @JOhn_Stuart, I have been using this kind of design lately also and find it quite interesting.

If you had a test file that took an interface how could you assert behaviour without knowing the type? If the types do not produce different behavior, how do they differ?

To me, a unit test needs to test the unit to which it is associated. Since interfaces are implemented implicitly, your type Tree may inadvertently implement any number of interfaces. The behavior of the Tree is only important to the users of the Tree, so its public API (String, Find etc) must be tested for its users.

This may lead to some similar code between the other graph types you implement, but to preserve a loose coupling they should be of no concern to one another. For illustration; should the adjacency matrix have any thoughts on how Add is implemented on the Tree ?

Perhaps you can reduce your repeated code by inheriting common behavior where possible. For instance; a type DirectedGraph may embed the type Graph like so:

type DirectedGraph struct {
   Graph
   backCheck T  // Some property to prevent backward traversal
}

This would allow you to implement your String, Find etc on Graph if they are the same for the DirectedGraph, and thus only test once, where they are implemented.

1 Like