Search code examples
unit-testingtypesclojuretype-conversiondouble

Clojure tests fails for identical expected and actual values


I'm doing a Clojure exercise that basically simulates a cars assemble factory. The following code is my "production" code.

(ns cars-assemble)

(def success-rate-frequencies [
  { :id 1 :interval #(= % 0), :rate 0 }
  { :id 2 :interval #(and (> % 0) (<= % 4)), :rate (/ 100 100) }
  { :id 3 :interval #(and (>= % 5) (<= % 8)), :rate (/ 90 100) }
  { :id 4 :interval #(= % 9), :rate (/ 80 100) }
  { :id 5 :interval #(>= % 10), :rate (/ 77 100) }
])

(defn get-rate-by-speed-interval [speed]
  (let [result (first (filter #((get % :interval) speed) success-rate-frequencies))]
    (get result :rate)))

(defn production-rate
  "Returns the assembly line's production rate per hour,
   taking into account its success rate"
  [speed]
  (float (* speed (* 221 (get-rate-by-speed-interval speed)))))

(defn working-items
  "Calculates how many working cars are produced per minute"
  [speed]
  (let [production-rate (production-rate speed)]
    (if (= speed 0) 0 (int (/ production-rate 60)))))

My problems is that for some reason when I run the tests, the production code returns the correct value, but the tests still fails. Down bellow I have my test example.

(deftest production-rate-speed-10-test
(testing "Production rate for speed 10"
  (is (= 1701.7 (cars-assemble/production-rate 10)))))

Here is the output of my command lean test:

FAIL in (production-rate-speed-10-test) (cars_assemble_test.clj:27)
Production rate for speed 10
expected: (= 1701.7 (cars-assemble/production-rate 10))
  actual: (not (= 1701.7 1701.7))

I tried to check if it would have any kind of hidden character, but did not find anything.

Another thing that I have tried was to manually modified the test file converting the expected value to float (like the example bellow). But I'm not supposed to change my test file.

(is (= (float 1701.7) (cars-assemble/production-rate 10)))

Solution

  • The = function checks if the params have the same type for floating values, so when you instantiate a decimal number like:

    (def my-decimal-number 12.000)
    

    You are actually instantiating a java.lang.Double. When you compare that with the value returned from production-rate function, you will receive a error because the types are different. Just to update the function production-rate to return a double instead.

    (defn production-rate
      "Returns the assembly line's production rate per hour,
       taking into account its success rate"
      [speed]
      (double (* speed (* 221 (get-rate-by-speed-interval speed)))))