You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
255 lines
11 KiB
255 lines
11 KiB
;;;; tests/main.lisp |
|
|
|
(in-package #:ritherdon-rest-tests) |
|
|
|
(def-suite all-tests |
|
:description "The master suite of all ritherdon-rest tests.") |
|
|
|
(in-suite all-tests) |
|
|
|
;;; HAD TO REVERT BACK TO FULL PACKAGE NAMES |
|
;;; ======================================== |
|
|
|
;;; BELOW EXPLAINS HOW YOU CAN OMIT PACKAGE NAMES FROM FUNCTION |
|
;;; CALLS. BUT, I'VE ADDED THE 'RATIFY' PACKAGE SINCE THEN AND I WAS |
|
;;; GETTING NAMING CONFLICTS (WITH 'TEST'). SO, I'VE HAD TO USE THE |
|
;;; FULL 'FIVEAM:TEST' FUNCTION CALLS. I'VE KEPT THE NOT FOR FUTURE |
|
;;; REFERENCE AND ADDED THIS AS EXTRA CONTEXT FOR WHEN/HOW TO OMIT |
|
;;; PACKAGE NAMES. |
|
|
|
;;; THIS BIT KINDA OUT-OF-DATE... |
|
|
|
;;; These two examples show the 'full' call to the fiveAm test |
|
;;; functions. This is just for reference. The 'namespace' is already |
|
;;; 'imported' in 'package.lisp'. |
|
|
|
;;; (fiveam:test sum-1 |
|
;;; (fiveam:is (= 3 (+ 1 2)))) |
|
|
|
;;; (fiveam:run!) |
|
|
|
;;; How you would normally create the tests -- with fiveAM already |
|
;;; set-up in 'package.lisp' and not needing to be explicit about it |
|
;;; here. This is similar to 'using static' in C#. |
|
|
|
(defun test-quasi() |
|
(run! 'all-tests)) |
|
|
|
;;; REST API Used Here is Temporary |
|
;;; =============================== |
|
;;; This REST API is a temporary one -- it's part of an artwork for |
|
;;; the Return to Ritherdon project. The intention is to retire the |
|
;;; API when the exhibition ends. So, these tests might fail because |
|
;;; the API is no longer active. |
|
|
|
|
|
;;; DEVICE STATUS TESTS |
|
;;; =================== |
|
;;; These tests are checking the 'shape' of the data returned by the |
|
;;; HTTP (REST) request matches what is expected. These tests are |
|
;;; expecting JSON data which looks similar to: |
|
|
|
;;; ((:ID . 79) (:STATUS . "off") (:TIME . "2021-07-01T16:00:001")). |
|
|
|
;;; ID: The row Id. in the database. |
|
;;; STATUS: The current power state of the device (I.E. on or off). |
|
;;; TIME: The timestamp when the status was recorded. |
|
|
|
;;; Usually, these updates are logged when each device is either just |
|
;;; finished powering up or as they are about to power down. |
|
|
|
(fiveam:test factory-1-status-data |
|
:description "Validates the (status) data produced by `FACTORY1'." |
|
(let ((data (ritherdon-rest:parse-request "/status/latest/1"))) |
|
;; Data should look something like: |
|
;; ((:ID . 79) (:STATUS . "off") (:TIME . "2021-07-01T16:00:001")). |
|
(is (= 3 (length data))) |
|
(is (equal t (consp data))) |
|
(is (equal ':id (first (nth 0 data)))) |
|
(is (equal ':status (first (nth 1 data)))) |
|
(is (equal ':time (first (nth 2 data)))) |
|
(is (equal t (typep (cdr (car data)) 'integer))) ; row :id number |
|
(is (> (cdr (car data)) 0)) |
|
(is (equal t (typep (cdr (car (cdr data))) 'string))) ; :status value |
|
(is (equal t (or (string-equal (cdr (car (cdr data))) "off") |
|
(string-equal (cdr (car (cdr data))) "on")))))) |
|
|
|
(fiveam:test factory-2-status-data |
|
:description "Validates the (status) data produced by `FACTORY2'." |
|
(let ((data (ritherdon-rest:parse-request "/status/latest/2"))) |
|
;; Data should look something like: |
|
;; ((:ID . 79) (:STATUS . "off") (:TIME . "2021-07-01T16:00:001")). |
|
(is (= 3 (length data))) |
|
(is (equal t (consp data))) |
|
(is (equal ':id (first (nth 0 data)))) |
|
(is (equal ':status (first (nth 1 data)))) |
|
(is (equal ':time (first (nth 2 data)))) |
|
(is (equal t (typep (cdr (car data)) 'integer))) ; row :id number |
|
(is (> (cdr (car data)) 0)) |
|
(is (equal t (typep (cdr (car (cdr data))) 'string))) ; :status value |
|
(is (equal t (or (string-equal (cdr (car (cdr data))) "off") |
|
(string-equal (cdr (car (cdr data))) "on")))))) |
|
|
|
(fiveam:test factory-3-status-data |
|
:description "Validates the (status) data produced by `FACTORY3'." |
|
(let ((data (ritherdon-rest:parse-request "/status/latest/3"))) |
|
;; Ritherdon has a third welding booth but it was not included in |
|
;; the art project so no light sensor was installed. Therefore, |
|
;; this should always return the 'default/initial/seed' data |
|
;; readings. |
|
;; Data should still take the same shape as factory1 and factory 2: |
|
;; ((:ID . 1) (:STATUS . "off") (:TIME . "2021-04-26T20:42:19.400868")). |
|
(is (= 3 (length data))) |
|
(is (equal t (consp data))) |
|
(is (equal ':id (first (nth 0 data)))) |
|
(is (equal ':status (first (nth 1 data)))) |
|
(is (equal ':time (first (nth 2 data)))) |
|
(is (equal t (typep (cdr (car data)) 'integer))) ; row :id number |
|
(is (> (cdr (car data)) 0)) |
|
(is (equal t (typep (cdr (car (cdr data))) 'string))) ; :status value |
|
(is (equal t (or (string-equal (cdr (car (cdr data))) "off") |
|
(string-equal (cdr (car (cdr data))) "on")))))) |
|
|
|
(fiveam:test gallery-1-status-data |
|
:description "Validates the (status) data produced by `GALLERY1'." |
|
;; Data should still take the same shape as others: |
|
;; ((:ID . 1) (:STATUS . "off") (:TIME . "2021-04-26T20:42:19.400868")) |
|
(let ((data (ritherdon-rest:parse-request "/status/latest/4"))) |
|
(is (= 3 (length data))) |
|
(is (equal t (consp data))) |
|
(is (equal ':id (first (nth 0 data)))) |
|
(is (equal ':status (first (nth 1 data)))) |
|
(is (equal ':time (first (nth 2 data)))) |
|
(is (equal t (typep (cdr (car data)) 'integer))) ; row :id number |
|
(is (> (cdr (car data)) 0)) |
|
(is (equal t (typep (cdr (car (cdr data))) 'string))) ; :status value |
|
(is (equal t (or (string-equal (cdr (car (cdr data))) "off") |
|
(string-equal (cdr (car (cdr data))) "on")))))) |
|
|
|
(fiveam:test gallery-2-status-data |
|
:description "Validates the (status) data produced by `GALLERY2'." |
|
;; Data should still take the same shape as others: |
|
;; ((:ID . 1) (:STATUS . "off") (:TIME . "2021-04-26T20:42:19.400868")) |
|
(let ((data (ritherdon-rest:parse-request "/status/latest/5"))) |
|
(is (= 3 (length data))) |
|
(is (equal t (consp data))) |
|
(is (equal ':id (first (nth 0 data)))) |
|
(is (equal ':status (first (nth 1 data)))) |
|
(is (equal ':time (first (nth 2 data)))) |
|
(is (equal t (typep (cdr (car data)) 'integer))) ; row :id number |
|
(is (> (cdr (car data)) 0)) |
|
(is (equal t (typep (cdr (car (cdr data))) 'string))) ; :status value |
|
(is (equal t (or (string-equal (cdr (car (cdr data))) "off") |
|
(string-equal (cdr (car (cdr data))) "on")))))) |
|
|
|
(fiveam:test gallery-3-status-data |
|
:description "Validates the (status) data produced by `GALLERY3'." |
|
;; This corresponds to 'factory3' -- no light sensor in welding |
|
;; booth 3 in Ritherdon. Therefore, no data to send. Because of |
|
;; this, the data returned here should be the 'seed data' unless |
|
;; I've manually updated it as part of another test. |
|
;; Data should still take the same shape as others: |
|
;; ((:ID . 1) (:STATUS . "off") (:TIME . "2021-04-26T20:42:19.400868")). |
|
(let ((data (ritherdon-rest:parse-request "/status/latest/6"))) |
|
(is (= 3 (length data))) |
|
(is (equal t (consp data))) |
|
(is (equal ':id (first (nth 0 data)))) |
|
(is (equal ':status (first (nth 1 data)))) |
|
(is (equal ':time (first (nth 2 data)))) |
|
(is (equal t (typep (cdr (car data)) 'integer))) ; row :id number |
|
(is (> (cdr (car data)) 0)) |
|
(is (equal t (typep (cdr (car (cdr data))) 'string))) ; :status value |
|
(is (equal t (or (string-equal (cdr (car (cdr data))) "off") |
|
(string-equal (cdr (car (cdr data))) "on")))))) |
|
|
|
|
|
;;; LIGHT READINGS TESTS |
|
;;; ==================== |
|
|
|
;;; Theses tests check the 'shape' of the light meter readings |
|
;;; returned by the HTTP (REST) requests. They make sure the data |
|
;;; matches what's expected. These tests are expecting JSON data along |
|
;;; the lines of: |
|
|
|
;;; ((:ID . 1855109) (:READING . 16) (:TIME . "2021-07-02T13:42:16")) |
|
|
|
;;; ID: The row Id. in the database. |
|
;;; READING: The amount of light recorded. |
|
;;; TIME: The timestamp when the reading was taken. |
|
|
|
;;; Because of how the light meters work, they do not always take |
|
;;; light meter readings at consistent intervals. But, both devices |
|
;;; aim to take a reading for as long as they are on. Also, Ritherdon |
|
;;; has three welding booths and the system has the capacity to record |
|
;;; all three booths. The Return to Ritherdon project decided on only |
|
;;; recording two of the booths so 'factory3' should only return it |
|
;;; seed data -- unless I've manually updated it (for another test |
|
;;; most likely). |
|
|
|
(fiveam:test factory-1-reading-data ; Had to add fiveam here because |
|
; of naming conflict with ratify |
|
; package. Comment at top of file |
|
; explaining further. |
|
:description "Validates the (light reading) data produced by `FACTORY1'." |
|
;; ((:ID . 1855109) (:READING . 16) (:TIME . "2021-07-02T13:42:16")) |
|
(let ((data (ritherdon-rest:parse-request "/readings/latest/1"))) |
|
(is-true (= 3 (length data))) |
|
(is-true (consp data)) |
|
(is (equal ':id (caar data))) |
|
(is (equal ':reading (caadr data))) |
|
(is (equal ':time (caaddr data))) |
|
(is-true (> (cdar data) 0)) ; Db Id numbers start at 0. |
|
(is-true (typep (cdadr data) 'integer)) ; reading can be <=> 0. |
|
;; Returns the date-time if data could be parsed. Returns `NIL' if |
|
;; it could not. Don't need to check if string. If system can't |
|
;; parse it doesn't matter what form the date-time is in. |
|
(is-false (equal (ratify:datetime-p (cdaddr data)) nil)))) ; time value. |
|
|
|
(fiveam:test factory-2-reading-data |
|
:description "Validates the (light reading) data produced by `FACTORY2'." |
|
;; ((:ID . 1855109) (:READING . 16) (:TIME . "2021-07-02T13:42:16")) |
|
(let ((data (ritherdon-rest:parse-request "/readings/latest/2"))) |
|
(is-true (= 3 (length data))) |
|
(is-true (consp data)) |
|
(is (equal ':id (caar data))) |
|
(is (equal ':reading (caadr data))) |
|
(is (equal ':time (caaddr data))) |
|
(is-true (> (cdar data) 0)) ; Db Id numbers start at 0. |
|
(is-true (typep (cdadr data) 'integer)) ; reading can be <=> 0. |
|
;; Returns the date-time if data could be parsed. Returns `NIL' if |
|
;; it could not. Don't need to check if string. If system can't |
|
;; parse it doesn't matter what form the date-time is in. |
|
(is-false (equal (ratify:datetime-p (cdaddr data)) nil)))) ; time value. |
|
|
|
(fiveam:test factory-3-reading-data |
|
:description "Validates the (light reading) data produced by `FACTORY3'." |
|
;; ((:ID . 1855109) (:READING . 16) (:TIME . "2021-07-02T13:42:16")) |
|
(let ((data (ritherdon-rest:parse-request "/readings/latest/3"))) |
|
(is-true (= 3 (length data))) |
|
(is-true (consp data)) |
|
(is (equal ':id (caar data))) |
|
(is (equal ':reading (caadr data))) |
|
(is (equal ':time (caaddr data))) |
|
(is-true (> (cdar data) 0)) ; Db Id numbers start at 0. |
|
(is-true (typep (cdadr data) 'integer)) ; reading can be <=> 0. |
|
;; This device is not active so the seed data should be |
|
;; returned. This data should not be produce `NIL' when Ratify |
|
;; tries to parse it (not a valid timestamp). If the timestamp can |
|
;; be parsed it most likely means I've updated the latest reading |
|
;; data (manually most likely) which should result in this failing |
|
;; because Ratify will return the parsed timestamp and not `NIL'. |
|
(is (equal (ratify:datetime-p (cdaddr data)) nil)))) ; time value. |
|
|
|
(fiveam:test all-device-status-data |
|
:description "Validates the status data produced when all status |
|
data for all devices is requested in the same API call." |
|
(let ((data (ritherdon-rest:parse-request "/status/latest"))) |
|
(is (= 6 (length data))) |
|
(is-true (consp data)) |
|
(is (equal ':|DEVICE 1| (car (first data)))) |
|
(is (equal ':|DEVICE 2| (car (second data)))) |
|
(is (equal ':|DEVICE 3| (car (third data)))) |
|
(is (equal ':|DEVICE 4| (car (fourth data)))) |
|
(is (equal ':|DEVICE 5| (car (fifth data)))) |
|
;; if 6 not last a big change has occurred. |
|
(is (equal ':|DEVICE 6| (caar (last data))))))
|
|
|