0

I am new to elixir and trying to learn some of it's features including the testing library ExUnit, but I am having some trouble understanding the concept of how to write and setup a test for a particular function and if I am going in the correct direction.

For example, to test if a list is ordered after getting data fr om a CSV file, would I need to actually call the function I wrote that does this or just provide a mock list of unordered data?

//Module function that parses the CSV file
  def parse_csv do
    @csv_path
    |> Path.expand(__DIR__)
    |> File.stream!
    |> CSV.decode
    |> CSV_MODULE.prioritize_claims
  end

Do I need to actually import that module function into my test file and then actually invoke it or do I just provide a sample test list that is unordered then pass the list to the function that is suppose to sort it.

henhen
  • 1,038
  • 3
  • 18
  • 36

3 Answers3

0

If you write a helper function to do just that and call it with the output you get from your parse_csv function you can and should just test it directly with the possible outputs you expect to get from that function.

If you want to test everything together it’s also a good option to have a sample CSV file, or even multiple to test that everything works as expected.

Ismael Abreu
  • 16,443
  • 6
  • 61
  • 75
0

do I just provide a sample test list that is unordered then pass the list to the function that is suppose to sort it

It depends what you want to test. If you just want to test the sorting behaviour, that works. I think you would import CSV_MODULE in your test file, then call CSV_MODULE.prioritize_claims with your test list, and assert the result is what you expect.

If you wanted to test parse_csv, you could write a known CSV to @csv_path in the test, then call your function. However, I think it would be better pass the path as an argument, rather than store it as a module attribute. You could still have a default value, but it allows you to provide a different one when necessary, including when testing.

Adam Millerchip
  • 20,844
  • 5
  • 51
  • 74
0

You should not test the core/library code, because using the library means you trust library authors.

That said, in your case, you test neither File.stream!/1 nor CSV.parse/1. All you need to test is your CSV_MODULE.prioritize_claims/1.

def parse_csv(csv_path \\ @csv_path) do
  csv_path
  |> Path.expand(__DIR__)
  |> File.stream!()
  |> CSV.decode()
  # Until here we call functions proven to work.
  # The result of the above would be the input
  # to the function below.
  # In tests, just pass alike input to the function  
  |> CSV_MODULE.prioritize_claims()
end
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • If `parse_csv` is public, it's still a good idea to have a test for the whole function, so that if the behaviour changes in the future, that change will be detected. – Adam Millerchip Aug 26 '23 at 06:17
  • @AdamMillerchip I disagree in general. We should not treat developers as idiots; once `parse_csv/1` has changed, its behavioral change is _expected_, isn’t it? I mean, if I change `+` to `-` in some function, I should not expect tests to catch it, it’s my sole responsibility. – Aleksei Matiushkin Aug 26 '23 at 06:26
  • You could make breaking change upgrade to the CSV library for example, which changes the decode behaviour. Without the test, you have only your memory/grep to remind you to fix the function - better hope there aren't other developers on your project, you are still around, and that you never forget anything :) – Adam Millerchip Aug 26 '23 at 06:29
  • The breaking change upgrade to the CSV library which changes the behavior of `decode/1`? I literally can hear thousands of developers screaming :)) – Aleksei Matiushkin Aug 26 '23 at 10:02