Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring test suite using StreamData #919

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

shinnokdisengir
Copy link
Contributor

TODO

refactoring test suite

Copy link

codecov bot commented Mar 29, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 65.48%. Comparing base (20fa298) to head (ef71037).
Report is 119 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #919      +/-   ##
==========================================
- Coverage   68.62%   65.48%   -3.14%     
==========================================
  Files         228      146      -82     
  Lines        6667     4288    -2379     
==========================================
- Hits         4575     2808    -1767     
+ Misses       2092     1480     -612     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@shinnokdisengir shinnokdisengir force-pushed the test-suite-2.0 branch 9 times, most recently from a386639 to ac30b5e Compare April 5, 2024 15:30
@shinnokdisengir shinnokdisengir force-pushed the test-suite-2.0 branch 4 times, most recently from 15808f7 to f8bc9a0 Compare April 15, 2024 11:07
@shinnokdisengir shinnokdisengir force-pushed the test-suite-2.0 branch 8 times, most recently from 4412eeb to ef42039 Compare April 23, 2024 15:17
@shinnokdisengir shinnokdisengir force-pushed the test-suite-2.0 branch 6 times, most recently from d4fff9e to 3fa3a8b Compare May 6, 2024 10:32
@shinnokdisengir shinnokdisengir force-pushed the test-suite-2.0 branch 11 times, most recently from 3c7cdd6 to a046b19 Compare May 10, 2024 09:28
Copy link
Collaborator

@Annopaolo Annopaolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, some files are missing the copyright header

apps/astarte_appengine_api/mix.exs Outdated Show resolved Hide resolved
apps/astarte_appengine_api/mix.exs Outdated Show resolved Hide resolved
apps/astarte_appengine_api/test/support_v2/common.ex Outdated Show resolved Hide resolved
"automaton_accepting_states" => :erlang.term_to_binary(:automaton_accepting_states),
"automaton_transitions" => :erlang.term_to_binary(:automaton_transitions),
"aggregation" => AggregationType.to_int(interface.aggregation),
# TODO Mapping to the other table
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently, select!(:interface) doesn't join with mapping table. It's need to be done

Copy link
Collaborator

@Annopaolo Annopaolo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's being done here is very good. In my opinion, the overall structure of tests can be improved for enhancing isolation and clarity. My suggestion is:
- A setup_all part in which a realm - whose name is randomly generated - is created, for each test file (i.e. each ExUnit.Case). This allows for non-interference of tests when running in parallel.
- A setup part, for each test, in which tables relevant for the test are populated and truncated on exit. This allows for non-interference of tests running in the same case and using the database.
- Note: cleanup is necessary only when tests change database state. For example, a test “fail to create group with invalid name” does not need a cleanup, as no group will be added to the db; a “succeeds to create group with valid input” will need cleanup.

In general, by looking at a single test it should be possible to clearly identify what is being created, what operation is being performed and what the expected output would be.

defmodule Astarte.AppEngine.API.V2DeviceTest do
use ExUnit.Case, async: true
use ExUnitProperties
use Astarte.Test.Cases.Device
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This use hides the setup step(s) needed to populate the db, so it is unclear where e.g. devices selected at line 39 do come from. It should be possible to clearly identify what is being created, what operation is being performed and what the expected output would be by just looking at a single test.
I find that explicitly implementing setup_all and setup in the test case helps doing so.

The same goes for the other tests on groups and interfaces.

###
### Delete
@delete_interface """
DELETE FROM :keyspace.interfaces WHERE name = :name
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If tests from different cases run in different keyspaces and, inside a case, each test populates the tables it needs and truncates them on exit, you get database isolation for free, without the need to write more complex queries for deleting only some data.
A quick sketch of a possible way of handling it:

defmodule MyTest do
  use ExUnit.Case
  
  setup_all do
     create_keyspace!("keyspace_#{System.unique_integer()}")
  end
  
  setup do
    # get keyspace from context 
    insert!(keyspace, devices_fixture())
    on_exit(fn -> run!("TRUNCATE TABLE devices") end)
  end

  test "my test 1" do
  # use the `devices` table
  end
end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have already discussed this with @rbino. The point is to write as little code as possible in each test file. Cases are made to achieve this

Comment on lines +6 to +35
def init(%{device_count: device_count, interfaces: interfaces}) do
{:ok, devices: DeviceGenerator.device(interfaces: interfaces) |> Enum.take(device_count)}
end

def setup(%{cluster: cluster, keyspace: keyspace, devices: devices}) do
on_exit(fn ->
DatabaseHelper.delete!(:device, cluster, keyspace, devices)
end)

DatabaseHelper.insert!(:device, cluster, keyspace, devices)
:ok
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two can be moved in (or called from) a setup block , instead of being in a different module

Comment on lines +13 to +27
setup_all [
{DeviceSetup, :init},
{DeviceSetup, :setup}
]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that setup_all runs once before all tests in a case. In order to improve test isolation and clarity, it would be better to generate device data for each test (i.e. with setup).
The same goes also for groups and interfaces

Changed
- using exandra -- waiting for database project
- implemented jwt + public/private key
- wip group tests
- squashed all failure
- polishing
- removed one_of_constant -> member_of
- splitted tests
- WIP device generator
- completed device generator...but using opaque data (TODO change it)
- basic datetime generator
- WIP device generator
- using Keyword.validate!
- WIP insert into db, IPNET error
- completed device WIP id doesn't match
- completed base tests device
- polishing
- renamed realm -> keyspace
- completed group generator + setup + case
- wip group test (group_name "!" doesn't work)
- added encoded_id field to device test
- unlinked Conn <-> Database cases
- fixed realm name
- fixed valid group name test
- added already exists
- polished
- removed common.ex

Signed-off-by: Gabriele Ghio <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants