defmodule RepeaterTest do
use ExUnit.Case
describe "duplicate/2" do
test "creates a new string, with the first argument duplicated a specified number of times" do
assert "aaaa" == Repeater.duplicate("a", 4)
end
end
end
defmodule RepeaterTest do
use ExUnit.Case
use ExUnitProperties
describe "duplicate/2" do
property "creates a new string, with the first argument duplicated a specified number of times" do
check all str <- string(:printable),
times <- integer(),
times >= 0 do
assert ??? == Repeater.duplicate(str, times)
end
end
end
end
defmodule RepeaterTest do
use ExUnit.Case
use ExUnitProperties
describe "duplicate/2" do
property "creates a new string, with the first argument duplicated a specified number of times" do
check all str <- string(:printable),
times <- integer(),
times >= 0 do
new_string = Repeater.duplicate(str, times)
assert String.length(new_string) == String.length(str) * times
assert Enum.all?(String.split(new_string, str), &(&1 == ""))
end
end
end
end
defmodule RepeaterTest do
use ExUnit.Case
describe "duplicating a string" do
test "duplicates the first argument a number of times equal to the second argument" do
assert "aaaa" == Repeater.duplicate("a", 4)
end
test "returns an empty string if the first argument is an empty string" do
assert "" == Repeater.duplicate("", 4)
end
test "returns an empty string if the second argument is zero" do
assert "" == Repeater.duplicate("a", 0)
end
test "works with longer strings" do
alphabet = "abcdefghijklmnopqrstuvwxyz"
assert "#{alphabet}#{alphabet}" == Repeater.duplicate(alphabet, 2)
end
end
end
defmodule Repeater do
def duplicate(list, 0) when is_list(list) do
[]
end
def duplicate(list, times) when is_list(list) do
list ++ duplicate(list, times - 1)
end
end
StreamData 的测试看起来可能是这样的:
defmodule RepeaterTest do
use ExUnit.Case
use ExUnitProperties
describe "duplicate/2" do
property "creates a new list, with the elements of the original list repeated a specified number or times" do
check all list <- list_of(term()),
times <- integer(),
times >= 0 do
new_list = Repeater.duplicate(list, times)
assert length(new_list) == length(list) * times
if length(list) > 0 do
assert Enum.all?(Enum.chunk_every(new_list, length(list)), &(&1 == list))
end
end
end
end
end
defmodule Repeater do
def duplicate(tuple, times) when is_tuple(tuple) do
tuple
|> Tuple.to_list()
|> Repeater.duplicate(times)
|> List.to_tuple()
end
end
这就是 Scott Wlaschin 提到的一种应用模式 "不同的路径,相同的终点"。这两种不同的处理顺序,最后生成的结果应该是一样的。让我们用这种方式来测试。
defmodule RepeaterTest do
use ExUnit.Case
use ExUnitProperties
describe "duplicate/2" do
property "creates a new tuple, with the elements of the original tuple repeated a specified number of times" do
check all t <- tuple({term()}),
times <- integer(),
times >= 0 do
result_1 =
t
|> Repeater.duplicate(times)
|> Tuple.to_list()
result_2 =
t
|> Tuple.to_list()
|> Repeater.duplicate(times)
assert result_1 == result_2
end
end
end
end
defmodule Repeater do
def duplicate(string, times) when is_binary(string) do
String.duplicate(string, times)
end
def duplicate(list, 0) when is_list(list) do
[]
end
def duplicate(list, times) when is_list(list) do
list ++ duplicate(list, times - 1)
end
def duplicate(tuple, times) when is_tuple(tuple) do
tuple
|> Tuple.to_list()
|> Repeater.duplicate(times)
|> List.to_tuple()
end
end
下面是基于特性的测试:
defmodule RepeaterTest do
use ExUnit.Case
use ExUnitProperties
describe "duplicate/2" do
property "creates a new string, with the first argument duplicated a specified number of times" do
check all str <- string(:printable),
times <- integer(),
times >= 0 do
new_string = Repeater.duplicate(str, times)
assert String.length(new_string) == String.length(str) * times
assert Enum.all?(String.split(new_string, str), &(&1 == ""))
end
end
property "creates a new list, with the elements of the original list repeated a specified number or times" do
check all list <- list_of(term()),
times <- integer(),
times >= 0 do
new_list = Repeater.duplicate(list, times)
assert length(new_list) == length(list) * times
if length(list) > 0 do
assert Enum.all?(Enum.chunk_every(new_list, length(list)), &(&1 == list))
end
end
end
property "creates a new tuple, with the elements of the original tuple repeated a specified number of times" do
check all t <- tuple({term()}),
times <- integer(),
times >= 0 do
result_1 =
t
|> Repeater.duplicate(times)
|> Tuple.to_list()
result_2 =
t
|> Tuple.to_list()
|> Repeater.duplicate(times)
assert result_1 == result_2
end
end
end
end