https://github.com/coryodaniel/organize-and-test-genservers
Just a repo of how I organize and test genservers
https://github.com/coryodaniel/organize-and-test-genservers
Last synced: 3 months ago
JSON representation
Just a repo of how I organize and test genservers
- Host: GitHub
- URL: https://github.com/coryodaniel/organize-and-test-genservers
- Owner: coryodaniel
- License: mit
- Created: 2020-12-03T20:43:36.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2020-12-03T20:47:06.000Z (over 5 years ago)
- Last Synced: 2025-12-31T04:59:58.612Z (7 months ago)
- Language: Elixir
- Size: 4.88 KB
- Stars: 0
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# How I test and layout genservers
## Set up and run tests & type checks
I tested a few different ways:
*DocTests on the public API of the GenServer (`lib/project.ex`)*
I like to consider my modules in the public API's directory to be "semi private" and test from the public interface.
I use dependency injection to put in the state, and I start a named instances of the GenServer for test isolation so tests can be async.
This validates the public API works as documented.
*ExUnit tests on the public API `test/tgs/project_test.exs`*
Similar to the tests in DocTest, but I use the exunit test ID as the genserver name.
This lets you have more involved tests that via DocTest, but then it doesn't validate the documentation. YMMV.
*DocTests on the functional logic of the GenServer (`lib/tgs/project/logic.ex`)
I don't like this since its a "semi private" model, but some people appreciate the functional tests without involving a genserver.
## How I layout GenServers
* `lib/project.ex` - Public API for the genserver
* `lib/project/logic.ex` - The business logic of the feature
* `lib/project/repository.ex` - The struct and type for the state of the genserver
* `lib/project/server.ex` - The genserver callback code
I consider any genserver callback a smell if its more than a single line of code, because all of the logic should be in `logic.ex`, except when doing a mutating `handle_call/3`.
```shell
mix deps.get
mix test --cover
mix dialyzer
```
## Interact w/ project storage
Run `iex -S mix`:
```elixir
{:ok, project} = Tgs.Project.start_link()
Tgs.Project.list_projects(project)
Tgs.Project.create_project(project, "my project")
```