wevote / WeVoteServer

We Vote's API application server written in Django/Python. Election data pulled from many sources, used by https://github.com/wevote/WebApp and https://github.com/wevote/WeVoteCordova and https://github.com/wevote/Campaigns.
https://api.wevoteusa.org
MIT License
50 stars 451 forks source link

Create a unit test for the voterPlanListRetrieve endpoint #1920

Closed utsab closed 1 year ago

utsab commented 2 years ago

To write a unit test test, here are a few recommendations to get started:

  1. Read this article which explains WeVoteServer's unit testing strategy.
  2. Take a look at the apis_v1/tests folder for examples of other tests.
  3. Launch WeVoteServer on your local machine and manually invoke the api endpoint. Understand the input parameters and the resulting JSON response.
  4. Search through the WeVoteServer codebase to locate the logic that gets executed when you manually invoke the api endpoint.
  5. Trace through the code to understand the intended behavior. Are there any edge cases or error conditions that the code checks for?
  6. Write a unit test that verifies at least one of the edge cases you discovered in your research for step 5.
tranngocsongtruc commented 2 years ago

Hi Utsab, thank you for posting the issue. Our team (Chris @chrisdedman, Luke @LukeBerryCS, and I) is working on it now. Could you please assign it to us? Thank you

tranngocsongtruc commented 1 year ago

@DaleMcGrew In the process of making a unit test for voterPlanListRetrieve endpoint, @chrisdedman, @LukeBerryCS, and I discovered an inconsistency in the way that the information is retrieved from the database compared to other endpoints.

Here is the trail of function calls for voterPlanListRetrieve:

  1. views_voter.py : voter_plan_save_view()
  2. voter_we_vote_id = fetch_voter_we_vote_id_from_voter_device_link(voter_device_id)
  3. voter/models.py: results = voter_manager.retrieve_voter_by_id(voter_id, read_only=True)

And as you see, one of the arguments is read_only = True, which means it reads from the read_only database instead of default database.

Comparison with another API endpoint - voterEmailAddressRetrieve:

The trail of function calls:

  1. views_voter.py: voter_email_address_retrieve_view()
  2. email_outbound/controllers.py: voter_email_address_retrieve_for_api()
  3. email_outbound/controllers.py: voter_results = voter_manager.retrieve_voter_from_voter_device_id(voter_device_id, read_only=False)

Note that now read_only=False, so the voterEmailAddressRetrieve endpoint reads from the default database whereas voterPlanListRetrieve reads from the read_only database. Thus, there is an inconsistency here. One consequence of this inconsistency is: the unit test for voterPlanListRetrieve endpoint seems to fail because (I'm guessing) that the read_only database does not get updated as quickly as the default database.

Suggested solution:

Change voterPlanListRetrieve to also read from default instead of read_only: results = voter_manager.retrieve_voter_by_id(voter_id, read_only=False)

What do you think of this solution?

utsab commented 1 year ago

@tranngocsongtruc, @chrisdedman, @LukeBerryCS - I spoke with Dale regarding your issue. He suggested one possible workaround. Before you read from the database to fetch the voter plan, add a sleep command to your test to make the test pause for 1-2 seconds. That should be enough time for the read-only database to get synchronized.