diff --git a/content/code/R/even_time_difference.R b/content/code/R/even_time_difference.R new file mode 100644 index 0000000..6411f0a --- /dev/null +++ b/content/code/R/even_time_difference.R @@ -0,0 +1,12 @@ +#' Check time to now even +#' +#' Checks whether time difference between now and given time in seconds is even +#' +#' @param seconds input time in whole seconds +#' +#' @return returns true or false +check_time_to_now_even <- function(seconds) { + if(seconds < 0) stop('received negative input') + now <- as.integer(format(Sys.time(), '%s')) + return((seconds - now) %% 2 == 0) +} diff --git a/content/code/R/reactor_temperature_sol.R b/content/code/R/even_time_difference_sol.R similarity index 100% rename from content/code/R/reactor_temperature_sol.R rename to content/code/R/even_time_difference_sol.R diff --git a/content/code/R/reactor_temperature.R b/content/code/R/reactor_temperature.R deleted file mode 100644 index 69b16cb..0000000 --- a/content/code/R/reactor_temperature.R +++ /dev/null @@ -1,16 +0,0 @@ -# reactor <- namespace::makeNamespace("reactor") -# assign("max_temperature", 100, env = reactor) -# namespaceExport(reactor, "max_temperature") - -#' Checks whether the temperature is above max_temperature -#' and returns the status. -#' -#' @param temperature_celsius The temperature of the core -#' @return 1 if the temperature is in range, otherwise 0 -check_reactor_temperature <- function(temperature_celsius) { - if (temperature_celsius > reactor::max_temperature) - status <- 1 - else - status <- 0 - status -} diff --git a/content/code/cpp/even_time_difference.cpp b/content/code/cpp/even_time_difference.cpp new file mode 100644 index 0000000..687fdac --- /dev/null +++ b/content/code/cpp/even_time_difference.cpp @@ -0,0 +1,11 @@ +#include +#include + +/* Checks whether temperature is above max_temperature and returns a status. */ +bool check_time_to_now_even(int seconds) { + if(seconds<0){ + throw std::runtime_error('received negative input'); + } + auto now = std::chrono::system_clock::now().time_since_epoch(); + return (std::chrono::duration_cast(now).count()-seconds)%2 ==0; +} diff --git a/content/code/cpp/even_time_difference_sol.cpp b/content/code/cpp/even_time_difference_sol.cpp new file mode 100644 index 0000000..5800fb8 --- /dev/null +++ b/content/code/cpp/even_time_difference_sol.cpp @@ -0,0 +1,54 @@ +// Changing variables included from headers (monkey patching) is not possible in +// C++. Instead we refactor the function to make it pure. +// Another way would be to use templates for dependency injection +#include + +// Making it pure, probably renaming would be a good idea +bool check_time_to_now_even(int seconds, int current_time) { + if (seconds < 0) { + throw std::runtime_error('received negative input'); + } + return (current_time - seconds) % 2 == 0; +} + +// Normal invocation +auto now = std::chrono::system_clock::now().time_since_epoch(); +int current_time_seconds = + std::chrono::duration_cast(now).count(); +check_time_to_now_even(4, current_time_seconds); + +TEST_CASE("Check time difference", "[reactor_state]") { + REQUIRE(check_time_to_now_even(1, 3) == true); + REQUIRE(check_time_to_now_even(4, 5) == false); +} + +// using templates + +template bool check_time_to_now_even(int seconds) { + if (seconds < 0) { + throw std::runtime_error('received negative input'); + } + int current_time = CLOCK.getNowSeconds(); + return (current_time - seconds) % 2 == 0; +} + +// Normal invocation +class ChronoClock { + + int getNowSeconds() { + auto now = std::chrono::system_clock::now().time_since_epoch(); + return std::chrono::duration_cast(now).count(); + } +}; + +check_time_to_now_even(3); + +class TestClock { + + int getNowSeconds() { return 3; } +}; + +TEST_CASE("Check time difference", "[reactor_state]") { + REQUIRE(check_time_to_now_even(3) == true); + REQUIRE(check_time_to_now_even(4) == false); +} \ No newline at end of file diff --git a/content/code/cpp/reactor_temperature.cpp b/content/code/cpp/reactor_temperature.cpp deleted file mode 100644 index cbbfee5..0000000 --- a/content/code/cpp/reactor_temperature.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "constants.hpp" -/* ^--- Defines the max_temperature constant as: -* namespace constants { -* constexpr double max_temperature = 100.0; -* } -*/ - -enum class ReactorState : int { FINE, CRITICAL }; - -/* Checks whether temperature is above max_temperature and returns a status. */ -ReactorState check_reactor_temperature(double temperature_celsius) { - return temperature_celsius > constants::max_temperature - ? ReactorState::CRITICAL - : ReactorState::FINE; -} diff --git a/content/code/cpp/reactor_temperature_sol.cpp b/content/code/cpp/reactor_temperature_sol.cpp deleted file mode 100644 index 37a1cb6..0000000 --- a/content/code/cpp/reactor_temperature_sol.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// Changing variables included from headers (monkey patching) is not possible in C++. -#include - -#include "reactor.hpp" - -TEST_CASE("Check reactor state", "[reactor_state]") { - REQUIRE(check_reactor_temperature(99) == ReactorState::FINE); - REQUIRE(check_reactor_temperature(100) == ReactorState::FINE); - REQUIRE(check_reactor_temperature(101) == ReactorState::CRITICAL); diff --git a/content/code/fortran/reactor_temperature.f90 b/content/code/fortran/even_time_difference.f90 similarity index 100% rename from content/code/fortran/reactor_temperature.f90 rename to content/code/fortran/even_time_difference.f90 diff --git a/content/code/fortran/reactor_temperature_sol.f90 b/content/code/fortran/even_time_difference_sol.f90 similarity index 100% rename from content/code/fortran/reactor_temperature_sol.f90 rename to content/code/fortran/even_time_difference_sol.f90 diff --git a/content/code/julia/reactor_temperature.jl b/content/code/julia/even_time_difference.jl similarity index 100% rename from content/code/julia/reactor_temperature.jl rename to content/code/julia/even_time_difference.jl diff --git a/content/code/julia/reactor_temperature_sol.jl b/content/code/julia/even_time_difference_sol.jl similarity index 100% rename from content/code/julia/reactor_temperature_sol.jl rename to content/code/julia/even_time_difference_sol.jl diff --git a/content/code/python/even_time_difference.py b/content/code/python/even_time_difference.py new file mode 100644 index 0000000..22841b5 --- /dev/null +++ b/content/code/python/even_time_difference.py @@ -0,0 +1,10 @@ +import time +def check_time_to_now_even(seconds): + """ + Checks whether time difference between now and given time in seconds is even + """ + if seconds < 0: + raise ValueError('received negative input') + + now=time.time() + return (seconds-now)%2 == 0 \ No newline at end of file diff --git a/content/code/python/even_time_difference_sol.py b/content/code/python/even_time_difference_sol.py new file mode 100644 index 0000000..d0b0b22 --- /dev/null +++ b/content/code/python/even_time_difference_sol.py @@ -0,0 +1,6 @@ +def test_check_time(monkeypatch): + def mocktime(): + return 2 + monkeypatch.setattr(time,"time",mocktime) + assert check_time_to_now_even(0) == 1 + assert check_time_to_now_even(1) == 0 \ No newline at end of file diff --git a/content/code/python/reactor_temperature.py b/content/code/python/reactor_temperature.py deleted file mode 100644 index 7e998f5..0000000 --- a/content/code/python/reactor_temperature.py +++ /dev/null @@ -1,10 +0,0 @@ -def check_reactor_temperature(temperature_celsius): """ - Checks whether temperature is above max_temperature - and returns a status. - """ - from reactor import max_temperature - if temperature_celsius > max_temperature: - status = 1 - else: - status = 0 - return status diff --git a/content/code/python/reactor_temperature_sol.py b/content/code/python/reactor_temperature_sol.py deleted file mode 100644 index d01317c..0000000 --- a/content/code/python/reactor_temperature_sol.py +++ /dev/null @@ -1,5 +0,0 @@ -def test_set_temp(monkeypatch): - monkeypatch.setattr(reactor, "max_temperature", 100) - assert check_reactor_temperature(99) == 0 - assert check_reactor_temperature(100) == 0 # boundary cases easily go wrong - assert check_reactor_temperature(101) == 1 diff --git a/content/test-design.md b/content/test-design.md index bf2cf62..d62b514 100644 --- a/content/test-design.md +++ b/content/test-design.md @@ -337,45 +337,44 @@ This one is not easy to test because the function has an external dependency. ````{tab} Python - ```{literalinclude} code/python/reactor_temperature.py + ```{literalinclude} code/python/even_time_difference.py :language: Python ``` ```` ````{tab} C++ - ```{literalinclude} code/cpp/reactor_temperature.cpp + ```{literalinclude} code/cpp/even_time_difference.cpp :language: c++ ``` ```` ````{tab} R - ```{literalinclude} code/R/reactor_temperature.R + ```{literalinclude} code/R/even_time_difference.R :language: R ``` ```` ````{tab} Julia - ```{literalinclude} code/julia/reactor_temperature.jl + ```{literalinclude} code/julia/even_time_difference.jl :language: julia ``` ```` ````{tab} Fortran - ```{literalinclude} code/fortran/reactor_temperature.f90 + ```{literalinclude} code/fortran/even_time_difference.f90 :language: fortran ``` ```` ````` ``````{solution} -This function depends on the value of -`reactor.max_temperature` so the function is not pure, so testing gets -harder. You could use monkey patching to override the value of -`max_temperature`, and test it with different values. [Monkey +This function depends on the current time, so the function is not pure, so testing gets +harder. You could use monkey patching to replace the time function with another function +, and test it with different values. [Monkey patching](https://en.wikipedia.org/wiki/Monkey_patch) is the concept of artificially changing some other value. @@ -385,35 +384,35 @@ A better solution would probably be to rewrite the function. ````{tab} Python - ```{literalinclude} code/python/reactor_temperature_sol.py + ```{literalinclude} code/python/even_time_difference_sol.py :language: Python ``` ```` ````{tab} C++ - ```{literalinclude} code/cpp/reactor_temperature_sol.cpp + ```{literalinclude} code/cpp/even_time_difference_sol.cpp :language: c++ ``` ```` ````{tab} R - ```{literalinclude} code/R/reactor_temperature_sol.R + ```{literalinclude} code/R/even_time_difference_sol.R :language: R ``` ```` ````{tab} Julia - ```{literalinclude} code/julia/reactor_temperature_sol.jl + ```{literalinclude} code/julia/even_time_difference_sol.jl :language: julia ``` ```` ````{tab} Fortran - ```{literalinclude} code/fortran/reactor_temperature_sol.f90 + ```{literalinclude} code/fortran/even_time_difference_sol.f90 :language: fortran ``` ````