Elisp testing example

I would like a simple function that returns t if a number/string have decimals or nil if it does not have decimals ignoring the type of the number.

Some cases I look for:

  • 0 returns nil.
  • 0.0 returns nil.
  • 1 returns nil.
  • 1.0 returns nil.
  • -43 returns nil.
  • -43.0 returns nil.
  • "2.0" returns nil.
  • "2" returns nil.
  • "foo" returns nil.
  • nil returns nil.
  • 1.1 returns t.
  • "2.5" returns t.

You can see my intentions.

First I will write the tests. I create a file called it-have-decimals-tests.el and I will write the tests.

If you want make a test in Emacs, you can use ert package. You can use ert-deftest to define a test and should to check if the result is as expected.

For example:

(ert-deftest test-example ()
  "Test 45"
  (should (it-have-decimals 45)))

You can run the tests with M-x ert.

Now I will write the tests for the future function it-have-decimals.

(add-to-list 'load-path "[path to it-have-decimals.el]")
(require 'it-have-decimals)
(require 'ert)
(require 'seq)


(ert-deftest test-nil ()
  "Test nil."
  (should (not (it-have-decimals nil))))

(ert-deftest test-it-have-decimals-zero ()
  "Test 0 and 0.0."
  (should (not (it-have-decimals 0)))
  (should (not (it-have-decimals 0.0))))

(ert-deftest test-it-have-decimals-integer ()
  "Test between -100 and 100. Integer
  Example: -100, -99, -98, ... 0, 1, 2, ... 100"
  (seq-doseq (i (number-sequence -100 100))
    (should (not (it-have-decimals i)))))

(ert-deftest test-it-have-decimals-float ()
  "Test between -100.0 and 100.0. Float.
  Example: -100.0, -99.0, -98.0, ... 0.0, 1.0, 2.0, ... 100.0"
  (seq-doseq (i (number-sequence -100 100))
    (should (not (it-have-decimals (float i))))))

(ert-deftest test-it-have-decimals-float-false ()
  "Test between 0.0 and 100.0. Float with random decimal number.
  Example: 0.1, 0.2, 0.3, ... 99.1, 99.2, 99.3"
  (seq-doseq (i (number-sequence -100 100))
    (should (it-have-decimals (+ i (/ (1+ (random 8)) 10.0))))))

(ert-deftest test-it-have-string ()
  "Test string."
  (should (not (it-have-decimals "foo"))))

(ert-deftest test-it-have-decimals-float-string ()
  "Test between 0.0 and 100.0. String with float number.
  Example: '0.0', '1.0', '2.0', ... '100.0'"
  (seq-doseq (i (number-sequence -100 100))
    (should (not (it-have-decimals (number-to-string (float i)))))))

(ert-deftest test-it-have-decimals-float-string-false ()
  "Test between 0.0 and 100.0. String with float number with random decimal number.
  Example: '0.1', '0.2', '0.3', ... '99.1', '99.2', '99.3'"
  (seq-doseq (i (number-sequence -100 100))
    (should (it-have-decimals (number-to-string (+ i (/ (1+ (random 8)) 10.0)))))))

(provide 'it-have-decimals-test)

Now I will write the function. I create a file called it-have-decimals.el. Remember to write the route to the file in the load-path variable in the tests file.

For example:

(add-to-list 'load-path "src/it-have-decimals.el")

I will write the function it-have-decimals in the file it-have-decimals.el.

(defun it-have-decimals (num)
  "Return t if NUM is have decimals."
  (let ((my-num (if (and
             (stringp num)
             ) ;; Return 0 if it is not a number
            (string-to-number num) num)))
    (when my-num (not (or (zerop my-num)   ;; Check if it is 0
              (integerp my-num) ;; Check if it is integer
              (and (floatp my-num) (equal my-num (float (truncate my-num)))) ;; Check if it is float
              )))))

(provide 'it-have-decimals)

Now I will run the tests.

M-x ert RET t

Or you can run the tests in the terminal.

emacs -batch -l ert -l it-have-decimals-tests.el -f ert-run-tests-batch-and-exit

The result is:

Running 8 tests
   passed  1/8  test-it-have-decimals-integer (0.000748 sec)
   passed  2/8  test-it-have-decimals-float (0.000716 sec)
   passed  3/8  test-it-have-decimals-float-false (0.000705 sec)
   passed  4/8  test-it-have-decimals-float-string (0.000895 sec)
   passed  5/8  test-it-have-decimals-float-string-false (0.000989 sec)
   passed  6/8  test-it-have-decimals-zero (0.000051 sec)
   passed  7/8  test-it-have-string (0.000040 sec)
   passed  8/8  test-nil (0.000033 sec)

Ran 8 tests, 8 results as expected, 0 unexpected

The tests are OK. 🎉

I hope this example helps you to write tests in Elisp. The package ert is very useful to improve the quality of your code.

Este trabajo está bajo una licencia Attribution-NonCommercial-NoDerivatives 4.0 International.

¿Me invitas a un café?

Puedes usar el terminal.

ssh customer@andros.dev -p 5555

Escrito por Andros Fenollosa

febrero 14, 2024

4 min de lectura

Sigue leyendo