pierrelegall

pierrelegall

Hello alchemists! :woman_scientist: :man_scientist:

Tests are supposed to be readable/maintainable as every code should be in a perfect world. And explicitness is a good thing for readability.

Beginning my “one kata per day”, I wrote FizzBuzz tests in two ways. I don’t really know which style I prefer: one is very explicit and less concise. The other one is more in a DRY style.

What’s your opinion about this? :face_with_monocle:

Version 1:

defmodule Kata.FizzBuzz.Test do
  use ExUnit.Case

  import Kata.FizzBuzz

  test "1, 2, 4, 7, 8 returns number as a string" do
    assert fizz_buzz(1) == "1"
    assert fizz_buzz(2) == "2"
    assert fizz_buzz(4) == "4"
    assert fizz_buzz(7) == "7"
    assert fizz_buzz(8) == "8"
  end

  test "3, 6, 9, 12 returns Fizz" do
    assert fizz_buzz(3) == "Fizz"
    assert fizz_buzz(6) == "Fizz"
    assert fizz_buzz(9) == "Fizz"
    assert fizz_buzz(12) == "Fizz"
  end

  test "5, 10, 20, 25 returns Buzz" do
    assert fizz_buzz(5) == "Buzz"
    assert fizz_buzz(10) == "Buzz"
    assert fizz_buzz(20) == "Buzz"
    assert fizz_buzz(25) == "Buzz"
  end

  test "15, 30, 45, 60 returns FizzBuzz" do
    assert fizz_buzz(15) == "FizzBuzz"
    assert fizz_buzz(30) == "FizzBuzz"
    assert fizz_buzz(45) == "FizzBuzz"
    assert fizz_buzz(60) == "FizzBuzz"
  end
end

Version 2:

defmodule Kata.FizzBuzz.Test do
  use ExUnit.Case

  import Kata.FizzBuzz

  test "1, 2, 4, 7, 8 returns number as a string" do
    [1, 2, 4, 7, 8]
    |> Enum.each(fn n -> assert fizz_buzz(n) == "#{n}" end)
  end

  test "3, 6, 9, 12 returns Fizz" do
    [3, 6, 9, 12]
    |> Enum.each(fn n -> assert fizz_buzz(n) == "Fizz" end)
  end

  test "5, 10, 20, 25 returns Buzz" do
    [5, 10, 20, 25]
    |> Enum.each(fn n -> assert fizz_buzz(n) == "Buzz" end)
  end

  test "15, 30, 45, 60 returns FizzBuzz" do
    [15, 30, 45, 60]
    |> Enum.each(fn n -> assert fizz_buzz(n) == "FizzBuzz" end)
  end
end

First Post!

codeanpeace

codeanpeace

Hmm, this is pretty subjective, but I’d personally go with a variant on Version 2 that swaps Enum.each for a for comprehension. I find it just reads better since it’s so close to spoken language i.e. “for each of these numbers, assert this condition”

  test "1, 2, 4, 7, 8 returns number as a string" do
    for n <- [1, 2, 4, 7, 8], do: assert fizz_buzz(n) == "#{n}"
  end

Since it’s generally good practice to avoid “magic strings” – or in this case numbers – when writing tests, we could generate the multiples. It’s probably a bit much to test something like FizzBuzz, but since it’s an exercise… might as well!

  test "multiple of fifteen aka three and five returns FizzBuzz" do
    for n <- 1..10, do: assert fizz_buzz(15 * n) == "FizzBuzz"
  end

Or maybe even throw in an Enum.random instead.

  test "multiple of fifteen aka three and five returns FizzBuzz" do
    assert fizz_buzz(15 * Enum.random(1..100)) == "FizzBuzz"
  end

Most Liked

hauleth

hauleth

My approach, as your is IMHO too repeating the implementation:

defmodule Kata.FizzBuzzTest do
  use ExUnit.Case
  use ExUnitProperties

  property "multiples of 3 contains `Fizz`" do
    check all n <- integer() do
      result = fizz_buzz(n * 3)
      assert String.contains?(result, "Fizz")
    end
  end

  property "multiples of 5 contains `Buzz`" do
    check all n <- integer() do
      result = fizz_buzz(n * 5)
      assert String.contains?(result, "Buzz")
    end
  end

  property "returned value is a binary" do
    check all n <- integer() do
      assert is_binary(fizz_buzz(n))
    end
  end

  property "result for 'plain' values is stringified integer" do
    check all n <- integer(), rem(n, 3) * rem(n, 5) != 0 do
      assert fizz_buzz(n) == Integer.to_string(n)
    end
  end
end

There probably could be some additional properties like the above

tfwright

tfwright

I think I am an outlier when it comes to tests, but I would not include any logic to generate assertions in unit tests. I would just choose one type of input for each type of output, with a test for each. If this logic was extra critical or issues keep popping up with unexpected inputs, I guess I would consider adding some sort of property based test to supplement the unit tests, but I would consider carefully before doing it.

LostKobrakai

LostKobrakai

To me the test labels also stand out the most. They should at best specify what needs to happen and not just repeat the examples.

At that point property testing (e.g. using stream_data) might become the more appropriate tool to use.

Last Post!

jarmo

jarmo

I always prefer explicit tests. Yes, they are more tedious to write, but much easier to understand when they start to fail.

Also, if trying to keep tests as DRY as production code then at one point they might get so complex that they need their own tests.

Where Next? Top

Trending in Discussions Top

cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New
achempion
I’ve been using Emacs as my main code editor for more than a two years. It’s a custom build version although I’ve tried doom emacs and sp...
New
budgie
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with. But I don’t use it anymore. Serverless was the promis...
New
jtormey
Lately I’ve been thinking about how to organize components as a LiveView application grows. One of the pain points I’ve found (for myself...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
georgeguimaraes
Just published claude-code-elixir, a plugin marketplace for Claude Code with Elixir support. These are the plugins I’ve been using for my...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews