0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IoTのセンサー値、「表示された」で終わらせず、「値の正しさ」を確かめるテストの考え方

0
Last updated at Posted at 2026-11-01

この記事は、Zennにも投稿しています。

はじめに

温度センサーの値をRaspberry Piで受け取り、データベースに保存して、ブラウザに表示する。IoTシステムを作ると、画面に値が出た時点で「動いた!」と安心してしまいがちです。

でも、画面に値が表示されることと、その値が正しいことは別の話です。センサーの値は、読み取り・通信・保存・計算・表示と何段階も経由して画面に届くので、どこかで値がずれていても、画面だけ見ていては気づけません。

この記事では、IoTシステムで「センサーの値が本当に正しいか」を確かめるための考え方と、具体的な方法をまとめます。

「表示される」と「正しい」は別のテスト

テストで確かめることは、大きく2つに分けられます。

種類 確かめること 例:温度の平均値を表示する機能
文法的(構文的)なテスト 処理がエラーなく動き、決まった形式で結果が出るか 平均値が画面に表示されるか
意味的なテスト 出てきた結果が、正しい値か 表示された平均値が、本当に正しい平均か

「画面に平均値が出た」ことを目で見て確認するのは、文法的なテストです。平均値の計算式が間違っていても、画面には何かしらの数字が出るので、このテストは通ってしまいます。

意味的なテストをするには、「正解の値」を用意して、それと比べる必要があります。ところがIoTでは、この正解が用意しにくいのが難しいところです。

  • 正解は現実の世界(部屋の本当の温度)にあり、プログラムの中にはない
  • センサー自体に誤差がある
  • 値が届くまでに、通信・保存・計算など多くの段階を経由する

そこで、段階ごとに正解を用意して確かめていきます。

センサー値の正しさを確かめる5つの方法

1. 決まった値を流して、出口の値と比べる

まずは、センサーを使わずに決まった値(定数)を流して、データベースや画面に同じ値が届くかを確かめます。センサーの値は毎回変わるので比べにくいですが、自分で決めた値なら「正解」がわかっています。

test_pipeline.py
import sqlite3

def save_reading(conn, temp, humid):
    conn.execute("INSERT INTO readings (temp, humid) VALUES (?, ?)", (temp, humid))
    conn.commit()

def test_保存した値がそのまま取り出せる():
    conn = sqlite3.connect(":memory:")
    conn.execute("CREATE TABLE readings (temp REAL, humid REAL)")

    # センサーの代わりに、決まった値を流す
    save_reading(conn, 25.5, 60.0)

    temp, humid = conn.execute("SELECT temp, humid FROM readings").fetchone()
    assert (temp, humid) == (25.5, 60.0)

この方法で、通信・保存・表示の経路で値が変わっていないことを確かめられます。例えば、「温度と湿度が入れ替わって保存されていた」「文字列を数値に変換するときに小数点以下が切り捨てられていた」といったバグは、ここで見つかります。

2. 計算した値は、手計算の結果と比べる

平均値や最大値など、プログラムで計算した値は、手で計算した答えと比べます。

test_average.py
import pytest

def average(values):
    if not values:
        return None  # データがないときの扱いを決めておく
    return sum(values) / len(values)

def test_平均値が正しい():
    # (20.0 + 22.0 + 24.0) / 3 = 22.0 を手で計算しておく
    assert average([20.0, 22.0, 24.0]) == pytest.approx(22.0)

def test_データがないとき():
    assert average([]) is None

ポイントは、データが0件のときのような境界のケースも一緒に確かめることです。0件で平均を計算すると、ゼロ除算でエラーになります。

小数の計算には誤差が出ることがあるので、== で比べるのではなく、pytest.approx のように誤差を許して比べます。

3. 基準になる計器と並べて比べる

センサーの値そのものが正しいかは、市販の温度計・湿度計をセンサーの横に置いて比べます。

このとき、「ぴったり同じ値になるか」ではなく、センサーの仕様にある精度の範囲に収まっているかで判断します。例えば、よく使われる温湿度センサーのDHT11は、精度が温度±2℃、湿度±5%RH程度とされています。温度計が25℃のとき、センサーが26℃を示していても、仕様の範囲内なので異常ではありません。

逆に、精度の範囲を大きく外れている場合は、センサーの故障や配線の問題、センサーの近くに熱を出す部品がある、などの原因が考えられます。

4. 環境をわざと変えて、値が反応するかを見る

値が「それらしく見える」だけで、実は固定値や古い値を表示し続けている、ということもあります。そこで、環境をわざと変えて、値がきちんと反応するかを確かめます。

確かめたいこと やり方
温度 センサーを手で包んで温める
湿度 センサーに息を吹きかける、濡れた布を近くに置く

見るポイントは、値が正しい向きに変わるか(温めたら上がるか)と、どれくらいの時間で画面に反映されるかです。反映までの時間がわかれば、「危険な温度になってから、何分後に通知が届くか」も説明できるようになります。

5. センサーの仕様と照らし合わせる

センサーのデータシート(仕様書)には、分解能(どれくらい細かい単位で値を出せるか)と測定範囲が書かれています。表示されている値が、これと矛盾していないかを確かめます。

例えば、DHT11の分解能は1℃・1%RHです。それなのに画面に「25.37℃」と表示されていたら、その細かい桁はセンサーが出したものではありません。平均を計算したときや、型を変換したときに生まれた桁です。

この場合は、表示する桁数をセンサーの分解能に合わせるほうが、利用者に誤解を与えません。

round(average_temp)  # 分解能が1℃なら、整数で表示する

また、測定範囲(DHT11なら温度0〜50℃)を外れた値が出たら、それは「とても暑い」のではなく、読み取りの失敗や故障かもしれません。範囲外の値は、通常のデータとは分けて扱うようにしておくと安全です。

値以外にも見落としがちなポイント

時刻は正しいか

センサーの値には、たいてい「いつ測ったか」の時刻を一緒に保存します。ところが、Raspberry Piの多くのモデルには、電源が切れている間も時刻を保つ時計(RTC)が付いていません。ネットワークにつながらない状態で起動すると、時刻がずれたまま記録されることがあります。

時刻がインターネット経由で正しく合わせられているかは、次のコマンドで確認できます。

timedatectl
# System clock synchronized: yes なら同期できている

ネットワークがない場所で使う場合は、RTCモジュールを追加することも検討しましょう。

同時に書き込んでも壊れないか

複数の処理(センサーからの受信と、ブラウザからの入力など)が同じファイルに書き込む場合、タイミングによってはデータが混ざったり、壊れたりすることがあります。書き込む間は**ロック(排他制御)**をかけて、同時に書き込まないようにします。

save_csv.py
import csv
import fcntl

def append_row(path, row):
    with open(path, "a", newline="") as f:
        fcntl.flock(f, fcntl.LOCK_EX)  # 書き込みが終わるまで、他の処理を待たせる
        csv.writer(f).writerow(row)
        f.flush()
        fcntl.flock(f, fcntl.LOCK_UN)

fcntl はLinuxやmacOSで使えるモジュールです(Windowsでは使えません)。

入力がない・おかしいときにどうなるか

ブラウザのフォームから値を登録できる場合は、何も入力せずに送信したときや、数値の欄に文字を入れたときの動きも確かめます。正常な値だけで確認していると、こうしたケースで処理が止まってしまうことに気づけません。

ログをファイルに残す

print でターミナルに出力するだけだと、ターミナルを閉じたら記録が消えてしまいます。長い時間動かし続けるIoTシステムでは、ログをファイルに残し、通常のログとエラーのログを分けておくと、あとから「いつ、何が起きたか」を追いやすくなります。

logger.py
import logging

logger = logging.getLogger("sensor")
logger.setLevel(logging.INFO)

info_handler = logging.FileHandler("sensor.log")         # すべてのログ
error_handler = logging.FileHandler("sensor_error.log")  # エラーだけ
error_handler.setLevel(logging.ERROR)

formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s")
for handler in (info_handler, error_handler):
    handler.setFormatter(formatter)
    logger.addHandler(handler)

logger.info("温度: 25.0℃ 湿度: 60%")
logger.error("センサーの読み取りに失敗しました")

まとめ

IoTシステムのテストでは、「値が表示されるか」だけでなく、「その値が正しいか」まで確かめることが大切です。確かめる内容をチェックリストにまとめます。

確かめること 方法
経路で値が変わっていないか 決まった値を流して、保存・表示された値と比べる
計算が正しいか 手計算の答えと比べる。データが0件のときも確かめる
センサーの値が正しいか 市販の計器と並べて、精度の範囲に収まるかを見る
値がきちんと反応するか 温める・湿らせるなど環境を変え、変化の向きと反映までの時間を見る
仕様と矛盾していないか 分解能より細かい桁が出ていないか、測定範囲を外れていないか
時刻・同時書き込み・異常な入力 時刻の同期、排他制御、空の入力のときの動きを確かめる

「画面に出たからOK」から一歩進んで、「この値は正しいと説明できる」状態を目指してみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?