diff --git a/metric.go b/metric.go
index fcbb1b291f2a9b95233671c50dcb6128f2dc136a..99ee30369629bb18a6751c7fa522be0f14d6cd58 100644
--- a/metric.go
+++ b/metric.go
@@ -1,6 +1,7 @@
 package telegraf
 
 import (
+	"bytes"
 	"time"
 
 	"github.com/influxdata/influxdb/client/v2"
@@ -68,6 +69,8 @@ func NewMetric(
 // a non-nil error will be returned in addition to the metrics that parsed
 // successfully.
 func ParseMetrics(buf []byte) ([]Metric, error) {
+	// parse even if the buffer begins with a newline
+	buf = bytes.TrimPrefix(buf, []byte("\n"))
 	points, err := models.ParsePoints(buf)
 	metrics := make([]Metric, len(points))
 	for i, point := range points {
diff --git a/metric_test.go b/metric_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..acf6dee994d72b33afd58f41d55f3e2a269401d1
--- /dev/null
+++ b/metric_test.go
@@ -0,0 +1,135 @@
+package telegraf
+
+import (
+	"fmt"
+	"math"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+)
+
+const validMs = `
+cpu,cpu=cpu0,host=foo,datacenter=us-east usage_idle=99,usage_busy=1 1454105876344540456
+`
+
+const invalidMs = `
+cpu, cpu=cpu0,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
+cpu,host=foo usage_idle
+cpu,host usage_idle=99
+cpu,host=foo usage_idle=99 very bad metric
+`
+
+const validInvalidMs = `
+cpu,cpu=cpu0,host=foo,datacenter=us-east usage_idle=99,usage_busy=1
+cpu,cpu=cpu1,host=foo,datacenter=us-east usage_idle=51,usage_busy=49
+cpu,cpu=cpu2,host=foo,datacenter=us-east usage_idle=60,usage_busy=40
+cpu,host usage_idle=99
+`
+
+func TestParseValidMetrics(t *testing.T) {
+	metrics, err := ParseMetrics([]byte(validMs))
+	assert.NoError(t, err)
+	assert.Len(t, metrics, 1)
+	m := metrics[0]
+
+	tags := map[string]string{
+		"host":       "foo",
+		"datacenter": "us-east",
+		"cpu":        "cpu0",
+	}
+	fields := map[string]interface{}{
+		"usage_idle": float64(99),
+		"usage_busy": float64(1),
+	}
+
+	assert.Equal(t, tags, m.Tags())
+	assert.Equal(t, fields, m.Fields())
+	assert.Equal(t, "cpu", m.Name())
+	assert.Equal(t, int64(1454105876344540456), m.UnixNano())
+}
+
+func TestParseInvalidMetrics(t *testing.T) {
+	metrics, err := ParseMetrics([]byte(invalidMs))
+	assert.Error(t, err)
+	assert.Len(t, metrics, 0)
+}
+
+func TestParseValidAndInvalidMetrics(t *testing.T) {
+	metrics, err := ParseMetrics([]byte(validInvalidMs))
+	assert.Error(t, err)
+	assert.Len(t, metrics, 3)
+}
+
+func TestNewMetric(t *testing.T) {
+	now := time.Now()
+
+	tags := map[string]string{
+		"host":       "localhost",
+		"datacenter": "us-east-1",
+	}
+	fields := map[string]interface{}{
+		"usage_idle": float64(99),
+		"usage_busy": float64(1),
+	}
+	m, err := NewMetric("cpu", tags, fields, now)
+	assert.NoError(t, err)
+
+	assert.Equal(t, tags, m.Tags())
+	assert.Equal(t, fields, m.Fields())
+	assert.Equal(t, "cpu", m.Name())
+	assert.Equal(t, now, m.Time())
+	assert.Equal(t, now.UnixNano(), m.UnixNano())
+}
+
+func TestNewMetricString(t *testing.T) {
+	now := time.Now()
+
+	tags := map[string]string{
+		"host": "localhost",
+	}
+	fields := map[string]interface{}{
+		"usage_idle": float64(99),
+	}
+	m, err := NewMetric("cpu", tags, fields, now)
+	assert.NoError(t, err)
+
+	lineProto := fmt.Sprintf("cpu,host=localhost usage_idle=99 %d",
+		now.UnixNano())
+	assert.Equal(t, lineProto, m.String())
+
+	lineProtoPrecision := fmt.Sprintf("cpu,host=localhost usage_idle=99 %d",
+		now.Unix())
+	assert.Equal(t, lineProtoPrecision, m.PrecisionString("s"))
+}
+
+func TestNewMetricStringNoTime(t *testing.T) {
+	tags := map[string]string{
+		"host": "localhost",
+	}
+	fields := map[string]interface{}{
+		"usage_idle": float64(99),
+	}
+	m, err := NewMetric("cpu", tags, fields)
+	assert.NoError(t, err)
+
+	lineProto := fmt.Sprintf("cpu,host=localhost usage_idle=99")
+	assert.Equal(t, lineProto, m.String())
+
+	lineProtoPrecision := fmt.Sprintf("cpu,host=localhost usage_idle=99")
+	assert.Equal(t, lineProtoPrecision, m.PrecisionString("s"))
+}
+
+func TestNewMetricFailNaN(t *testing.T) {
+	now := time.Now()
+
+	tags := map[string]string{
+		"host": "localhost",
+	}
+	fields := map[string]interface{}{
+		"usage_idle": math.NaN(),
+	}
+
+	_, err := NewMetric("cpu", tags, fields, now)
+	assert.Error(t, err)
+}
diff --git a/plugins/outputs/prometheus_client/prometheus_client_test.go b/plugins/outputs/prometheus_client/prometheus_client_test.go
index 34ef77e4cd024eb0adf35477beea0736174be55b..2630e6262a68cc3f7acb2da8e548ca8033abc463 100644
--- a/plugins/outputs/prometheus_client/prometheus_client_test.go
+++ b/plugins/outputs/prometheus_client/prometheus_client_test.go
@@ -16,9 +16,12 @@ func TestPrometheusWritePointEmptyTag(t *testing.T) {
 	if testing.Short() {
 		t.Skip("Skipping integration test in short mode")
 	}
+	pTesting = &PrometheusClient{Listen: "localhost:9127"}
+	pTesting.Start()
+	defer pTesting.Stop()
 
 	p := &prometheus.Prometheus{
-		Urls: []string{"http://localhost:9126/metrics"},
+		Urls: []string{"http://localhost:9127/metrics"},
 	}
 	tags := make(map[string]string)
 	pt1, _ := telegraf.NewMetric(
@@ -51,33 +54,24 @@ func TestPrometheusWritePointEmptyTag(t *testing.T) {
 		acc.AssertContainsFields(t, "prometheus_"+e.name,
 			map[string]interface{}{"value": e.value})
 	}
-}
-
-func TestPrometheusWritePointTag(t *testing.T) {
-	if testing.Short() {
-		t.Skip("Skipping integration test in short mode")
-	}
 
-	p := &prometheus.Prometheus{
-		Urls: []string{"http://localhost:9126/metrics"},
-	}
-	tags := make(map[string]string)
+	tags = make(map[string]string)
 	tags["testtag"] = "testvalue"
-	pt1, _ := telegraf.NewMetric(
+	pt3, _ := telegraf.NewMetric(
 		"test_point_3",
 		tags,
 		map[string]interface{}{"value": 0.0})
-	pt2, _ := telegraf.NewMetric(
+	pt4, _ := telegraf.NewMetric(
 		"test_point_4",
 		tags,
 		map[string]interface{}{"value": 1.0})
-	var metrics = []telegraf.Metric{
-		pt1,
-		pt2,
+	metrics = []telegraf.Metric{
+		pt3,
+		pt4,
 	}
 	require.NoError(t, pTesting.Write(metrics))
 
-	expected := []struct {
+	expected2 := []struct {
 		name  string
 		value float64
 	}{
@@ -85,16 +79,9 @@ func TestPrometheusWritePointTag(t *testing.T) {
 		{"test_point_4", 1.0},
 	}
 
-	var acc testutil.Accumulator
-
 	require.NoError(t, p.Gather(&acc))
-	for _, e := range expected {
+	for _, e := range expected2 {
 		acc.AssertContainsFields(t, "prometheus_"+e.name,
 			map[string]interface{}{"value": e.value})
 	}
 }
-
-func init() {
-	pTesting = &PrometheusClient{Listen: "localhost:9126"}
-	pTesting.Start()
-}