This week I have released my two first contributions to the elixir open source community in
hex
:
Galena
and
Conejo
.
Galena is a library based on GenStage that will help you to create your topic producer-consumer data pipelines.
Conejo is an OTP application/library that facilitate the creation of publishers and consumers of RabbitMQ or AMQP servers. It is based on the library amqp .
Galena is a library based on GenStage that will help you to create your topic producer-consumer data pipelines.
Conejo is an OTP application/library that facilitate the creation of publishers and consumers of RabbitMQ or AMQP servers. It is based on the library amqp .
I am very surprised that most of the questions that I have received are about the tests:
"How do you test the libraries if they provide Behaviours to develop concurrent apps?"
Let's see how.
"How do you test the libraries if they provide Behaviours to develop concurrent apps?"
Let's see how.
Testing
Elixir has a really good unit test framework,
ExUnit
, which is really easy to use. Otherwise we are talking about concurrent apps, where more of the logic will be executed in different processes, because we want to scale and Elixir allows you to do it, and ExUnit will only pass a test if the assert function is in the main process.
As we have already mentioned we are using Elixir and we use the Actor Model, therefore we can send messages between the processes. Let's see how to use it for testing.
As we have already mentioned we are using Elixir and we use the Actor Model, therefore we can send messages between the processes. Let's see how to use it for testing.
Register the main Process
The first step is to register the process where the test is running:
The first step is to register the process where the test is running:
test "receive message" do Process.register(self(), :main_process) ...
Send the message with the result to the Main Process
The callback which will handle the message in the secondary process, has to send the result to the main process.
The callback which will handle the message in the secondary process, has to send the result to the main process.
... def handle_message(message) do result = do_work(message) send(:main_process, result) ... end ...
Check the result in the Main Process
Finally we have to check the result in the main process. Sometimes, we are only interested in knowing that the message was processed by the secondary process and sent to the main one:
Finally we have to check the result in the main process. Sometimes, we are only interested in knowing that the message was processed by the secondary process and sent to the main one:
# Main Process ... Logger.info("Waiting for the message ...") assert_receive(message, timeout)
But in other cases we also want to check that the secondary process executed its transformation well. (Assuming that the message is a tuple with a topic and a result)
# Main Process ... receive do {topic, result} -> assert topic == expected_topic assert result == expected_result msg -> assert false end