Testing: Basics
Testing Functions
Code
(ns testing-basics.core
(:require [clojure.test :refer [are deftest is run-all-tests run-tests
testing]]))
;; ---
;; Testing functions
;; ---
;; Basic functions
(defn sum [a b]
(+ a b))
(deftest sum-test
(is (= 3 (sum 1 2)))
(is (= 0 (sum 1 -1))))
(deftest sum-test-with-setup
(let [a 1]
(is (= 3 (sum a 2)))
(is (= 0 (sum a -1)))))
(defn subtract [a b]
(- a b))
(deftest subtract-test
(are [x y] (= x y)
0 (subtract 1 1)
-1 (subtract 1 2)))
;; Function with multiple arities
(defn greeting
([] (greeting "World" "Hello"))
([name] (greeting name "Hello"))
([name salutation] (str salutation ", " name "!")))
(deftest greeting-test
(is (= "Hello, World!"
(greeting)))
(is (= "Hello, John!"
(greeting "John")))
(is (= "Good morning, John!"
(greeting "John" "Good morning"))))
;; Function that throws an exception
(defn throws-exception []
(throw (Exception. "This function throws an exception")))
(deftest throws-exception-test
(is (thrown? Exception
(throws-exception))))
(run-tests 'testing-basics.core)
;; => {:test 6, :pass 13, :fail 0, :error 0, :type :summary}
(run-all-tests)
;; => {:test 6, :pass 13, :fail 0, :error 0, :type :summary}Explanation
This Clojure code demonstrates basic unit testing practices in the language. Here’s a breakdown of what the code does:
- Namespace declaration: The script starts with the
(ns ...)form which stands for ’namespace’. This specifies the namespacetesting-basics.corewhere the following code will reside. - Require statement: The
:requirekeyword within the namespace declaration is used to import necessary dependencies, in this case, various testing functionalities provided by theclojure.testlibrary. - Function definition (sum):
(defn sum [a b] (+ a b))defines a functionsumthat takes two arguments,aandb, and returns their sum. - Test definition for sum:
(deftest sum-test ...)defines a test calledsum-testwhich verifies that thesumfunction works as expected. It uses theisfunction to assert that the result of thesumfunction is equal to the expected value for two different sets of inputs. - Test definition with setup for sum:
sum-test-with-setupis another test for thesumfunction. It utilizesletto bind a value toabefore the assertions. This is useful for providing setup for a test. - Function definition (subtract):
(defn subtract [a b] ...)defines a functionsubtractthat takes two arguments,aandb, and returns the result of subtractingbfroma. - Test definition for subtract:
subtract-testis a test for thesubtractfunction. It uses thearemacro, which allows for more concise repetitive tests by defining a template for the test, which is then repeated for each group of inputs. - Function definition with multiple arities (greeting):
greetingis a function with multiple arities, meaning it can take different numbers of arguments. This function returns a greeting based on the number and type of arguments given. - Test definition for greeting:
greeting-testdefines a test for thegreetingfunction, asserting the expected output for three different sets of inputs. - Function definition (throws-exception):
throws-exceptionis a function that simply throws an exception when called. - Test definition for throws-exception:
throws-exception-testis a test that checks if thethrows-exceptionfunction indeed throws an exception as expected. Thethrown?macro is used to check if an exception of a specific type is thrown. - Running the tests:
(run-tests 'testing-basics.core)runs all tests in thetesting-basics.corenamespace. Similarly,(run-all-tests)runs all tests in all namespaces. The results (summary statistics) of the tests are returned.
This Clojure code defines several functions and their corresponding tests, then runs them. It demonstrates the basic usage of the clojure.test library for testing Clojure code.
Organizing the Tests
Code
(ns testing-basics.core
(:require [clojure.test :refer [are deftest is run-all-tests run-tests
testing]]))
;; ---
;; Organizing the tests
;; ---
(defn divide [a b]
(if (zero? b)
(throw (IllegalArgumentException. "Cannot divide by zero"))
(/ a b)))
(deftest divide-test
(testing "Positive case"
(is (= 2 (divide 4 2)))
(is (= 1/2 (divide 1 2))))
(testing "Negative case"
(is (thrown? IllegalArgumentException
(divide 4 0)))))Explanation
Let’s break down the Clojure code snippet:
(ns testing-basics.core (:require [clojure.test :refer [are deftest is run-all-tests run-tests testing]]))- This is the namespace declaration for the module. It defines a new namespacetesting-basics.coreand requires a set of testing-related functions from theclojure.testlibrary. The functions that are referred for use in this namespace areare,deftest,is,run-all-tests,run-tests, andtesting.(defn divide [a b] (if (zero? b) (throw (IllegalArgumentException. "Cannot divide by zero")) (/ a b)))- This functiondividetakes two arguments,aandb. It checks ifbis zero, if it is, then anIllegalArgumentExceptionis thrown with a message “Cannot divide by zero”. Ifbis not zero, thenais divided byband the result is returned.deftest- This is a macro provided by theclojure.testlibrary for defining a test.(deftest divide-test (testing "Positive case" (is (= 2 (divide 4 2))) (is (= 1/2 (divide 1 2)))) (testing "Negative case" (is (thrown? IllegalArgumentException (divide 4 0)))))- This defines a test suite nameddivide-testwith two test scenarios.(testing "Positive case" (is (= 2 (divide 4 2))) (is (= 1/2 (divide 1 2))))- This is the first testing scenario, labeled as “Positive case”. It checks two conditions:- The first condition
(is (= 2 (divide 4 2)))checks if the functiondividereturns2when arguments4and2are passed. - The second condition
(is (= 1/2 (divide 1 2)))checks if the functiondividereturns1/2when arguments1and2are passed.
- The first condition
(testing "Negative case" (is (thrown? IllegalArgumentException (divide 4 0))))- This is the second testing scenario, labeled as “Negative case”. It checks if anIllegalArgumentExceptionis thrown when4and0are passed to thedividefunction, which is expected because you cannot divide by zero.
These tests can then be run using the run-tests function from clojure.test, which will provide a report detailing the success or failure of each test case.
Last updated on