Skip to content

Commit

Permalink
add Integration Tests using mosquitto as MQTT broker
Browse files Browse the repository at this point in the history
  • Loading branch information
Svedrin committed Dec 23, 2019
1 parent 290c0d2 commit 81c75e2
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 3 deletions.
16 changes: 15 additions & 1 deletion .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,21 @@
kind: pipeline
name: default

services:
- name: broker
image: eclipse-mosquitto

steps:
- name: run tests
image: alpine:latest
commands:
- apk add --no-cache python3
- cp -r /drone/src /tmp/src
- pip3 install --no-cache-dir -r /tmp/src/requirements.txt
- pip3 install --no-cache-dir behave
- mv /tmp/src/config.tests.toml /tmp/src/config.toml
- cd /tmp/src && python3 -m behave

- name: build docker image
image: plugins/docker
settings:
Expand All @@ -18,6 +32,6 @@ steps:
- pull_request
---
kind: signature
hmac: dca1de31b29a4f2d489969ddd585c5eb52d1dfeea4fddaa21e80872625ee61b0
hmac: 08431f201762d04937c91712bd562f1ac689ddab046de1cc06f74fdfbd3f2853

...
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
config.toml
__pycache__/
37 changes: 37 additions & 0 deletions config.tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copy this file to config.toml to use it.

[exporter]
listen = "0.0.0.0"
port = 9466

# Configure your MQTT broker's address and credentials here.
[mqtt]
client_id = "mqtt_pushgw-%(hostname)s"
broker = "broker"
port = 1883
username = ""
password = ""

# List some keys we should subscribe to. Use '#' to subscribe to *everything*.
# We will ignore any messages that can't be directly parsed as floats.
subscribe = [
'sensor/#',
"otherTopic"
]

# Expire metrics after 5 Minutes. Can be overridden in the [[topic]] sections.
# Comment to disable.
expire = 300


[[topic]]
match = 'sensor/(?P<sensor_name>\w+)/(?P<__metric__>\w+)'

[[topic]]
match = 'sensor/slow_sensor/super_slow_metric'
expire = 900
metric = "just_a_metric"

[[topic]]
match = 'sensor/sucky_sensor/.*'
ignore = true
12 changes: 12 additions & 0 deletions features/environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from time import time

import paho.mqtt.client as mqtt

def before_all(context):
client = mqtt.Client(client_id="IT")
client.connect("broker", 1883)

def publish(topic, payload):
client.publish(topic, payload)

context.publish = publish
26 changes: 26 additions & 0 deletions features/mqtt.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Feature: MQTT stuff.

Scenario: Float values

Given app is running
when Topic sensor/bathroom/temperature receives message with payload "15.2"
then Metric 'temperature{sensor_name="bathroom",mqtt_topic="sensor/bathroom/temperature"}' exists
and its value is equal to 15.2
and Metric 'mqtt_data_age{sensor_name="bathroom",mqtt_topic="sensor/bathroom/temperature",metric="temperature"}' exists
and its value is less than 0.5

Scenario: String values

Given app is running
when Topic sensor/bathroom/window receives message with payload "OPEN"
then Metric 'window{sensor_name="bathroom",mqtt_topic="sensor/bathroom/window",window="OPEN"}' exists
and its value is equal to 1.0
and Metric 'mqtt_data_age{sensor_name="bathroom",mqtt_topic="sensor/bathroom/window",metric="window"}' exists
and its value is less than 0.5
when Topic sensor/bathroom/window receives message with payload "CLOSED"
then Metric 'window{sensor_name="bathroom",mqtt_topic="sensor/bathroom/window",window="OPEN"}' exists
and its value is equal to 0.0
and Metric 'window{sensor_name="bathroom",mqtt_topic="sensor/bathroom/window",window="CLOSED"}' exists
and its value is equal to 1.0
and Metric 'mqtt_data_age{sensor_name="bathroom",mqtt_topic="sensor/bathroom/window",metric="window"}' exists
and its value is less than 0.5
62 changes: 62 additions & 0 deletions features/steps/mqtt_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# encoding: utf-8

import threading

from time import sleep
from behave import given, when, then

import mqtt_pushgateway

def get_metrics():
prom_data = mqtt_pushgateway.http_metrics().data.decode("UTF-8")

def floatify(line):
key, val = line.split()
return key, float(val)

return dict([
floatify(line)
for line in prom_data.split("\n")
if line
])

@given('App is running')
def step(context):
context.mqtt_pushgateway = threading.Thread(target=mqtt_pushgateway.main)
context.mqtt_pushgateway.daemon = True
context.mqtt_pushgateway.start()
context.dirty = False
context.metrics = {}
sleep(0.1)

@when('Topic {topic} receives message with payload "{payload}"')
def step(context, topic, payload):
context.dirty = True
context.publish(topic, payload.encode("UTF-8"))

@then("Metric '{metric}' exists")
def step(context, metric):
# Refresh context.metrics if necessary
if context.dirty or not context.metrics:
sleep(0.1)
context.metrics = get_metrics()

if metric not in context.metrics:
print("####\nMetric does not exist:\n %s\nThese metrics do exist:\n%s\n####\n" % (
metric, "\n".join([ " * %s" % m for m in context.metrics])
))
assert metric in context.metrics, "metric does not exist, see stdout for details"

context.metric_value = context.metrics[metric]

@then("its value is equal to {value:f}")
def step(context, value):
assert context.metric_value == value, "Value %f is not == %f" % (context.metric_value, value)

@then("its value is less than {value:f}")
def step(context, value):
assert context.metric_value < value, "Value %f is not < %f" % (context.metric_value, value)

@then("its value is more than {value:f}")
def step(context, value):
assert context.metric_value > value, "Value %f is not > %f" % (context.metric_value, value)
4 changes: 2 additions & 2 deletions mqtt_pushgateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import time
import json

import paho.mqtt.client as mqttClient
import paho.mqtt.client as mqtt

from collections import defaultdict
from datetime import datetime, timedelta
Expand Down Expand Up @@ -153,7 +153,7 @@ def on_message(client, userdata, message):
logging.warning("Metric update for '%s' failed" % topic, exc_info=True)

def main():
client = mqttClient.Client(config["mqtt"]["client_id"] % dict(
client = mqtt.Client(config["mqtt"]["client_id"] % dict(
hostname=socket.gethostname()
))
client.username_pw_set(config["mqtt"]["username"], config["mqtt"]["password"])
Expand Down

0 comments on commit 81c75e2

Please sign in to comment.