Goでmqtt brokerのE2Eテストを書きたい

2024-04-01

Channel

RustでMQTT Brokerを作成して、テストを書こうと思ったときに、GoのChannelで実現できる挙動は強力な味方となってくれます。 下記のようにChannelに受け取ったものを流すことができます。

channel := make(chan mqtt.Message)
var f mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
    log.Printf("Sub data: %v\n", msg)
    channel <- msg
}

if token := c.Subscribe(topic, qos, f); token.Wait() && token.Error() != nil {
    log.Printf("Mqtt subscribe error %s", token.Error())
    return nil, token.Error()
} else {
    log.Println("Subscribe Success")
}

テストを書くとしたらタイムアウトも必須だと思うが、下記のようにselectを使って書くと良いと思います。

func TestPubSub(t *testing.T) {
    publishPayload := "data"
    messageChannel := subscribeWaitFirstPacket("topic_a", publishPayload)
    Publish("topic_a")

    select {
        case msg := <- messageChannel:
            assert(msg, expect)
        case <- time.After(timeoutSecond):
            t.Error("")
    }

}
//動くコードではない

stretchr/testify

Goで書かれたモジュールは標準のtestingパッケージを利用すれば充分テストできると思っていましたが、他の言語で書かれたソフトウェアを統合/E2Eテストしようと思った際に、testing.Mを駆使すれば標準パッケージでやることも不可能ではないが、テストの前後にやることが多くなってきてtestingだけだと心もとない。そこで、stretchr/testifyのSuiteモジュールを使えば、前後で別ソフトウェアをbuild/runできるので便利そうです。

stretchr/testifyは他にも便利な機能がありそうなので使いこなしたいです。

type OriginalSuite struct {
 suite.Suite
}

func (suite *OriginalSuite) SetupSuite() {
 suite.T().Log("SetupSuite")
 //ソフトウェアをbuildする
}
func (suite *OriginalSuite) TearDownSuite() {
 suite.T().Log("TearDownSuite")
}
func (suite *OriginalSuite) SetupTest() {
 suite.T().Log("SetupTest")
}
func (suite *OriginalSuite) TearDownTest() {
 suite.T().Log("TeardownTest")
}
func (suite *OriginalSuite) BeforeTest(suiteName, testName string) {
 suite.T().Log("BeforeTest")
 //ソフトウェアを実行する
 //testNameに応じて起動オプションを変更する
}
func (suite *OriginalSuite) AfterTest(suiteName, testName string) {
 suite.T().Log("AfterTest")
}
func (suite *OriginalSuite) TestHoge() {
 suite.T().Log("TestHoge")
}
func (suite *OriginalSuite) TestFuga() {
 suite.T().Log("TestFuga")
}

// テスト実行
func TestSuite(t *testing.T) {
 suite.Run(t, new(OriginalSuite))
}

この記事からtestifyを知りました Goテストモジュール Testifyをつかってみた - classmethod

自作のmqtt brokerのテストで下記のように使っています。 統合テスト例: integration_test/mqtt_test.go

XでShare