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

fix and refactor migrations test teardown and setup #76

Merged
merged 7 commits into from
May 10, 2020

Conversation

skarzi
Copy link
Collaborator

@skarzi skarzi commented May 9, 2020

Closes #38
Closes #40

This commit implements new migrations test teardown and setup.
Teardown simply call migrate command, but on already tested database.
Setup is more complicated but more similar to real case of running migrations on production (I described it pros in #38) :

  • drop all models tables
  • flush (make empty) django_migrations table
  • create as broad as possible plan including all migrate_from targets
  • apply all migrations (only forward - so like in production environments and avoid any potential side effects implemented in backward migrations)

This part related to custom plan creation is necessary to make API developers' friendly just to not force them to include migrations targets for all models they want to use in test.
Generated plan cause also .after() applies migrations more like its done on production (only these migrations that aren't applied yet will be applied - on production all older migrations are already applied), because it is just truncated full (clean) migrations plan.

skarzi added 6 commits May 9, 2020 16:42
Move ``_Migration`` and ``_MigrationSpec`` to newly introduced module
and rename them to ``MigrationTarget`` and ``MigrationSpec``.
Fix type hints of ``MigratorTestCase`` class attributes:
``migrate_from`` and ``migrate_to``.
@skarzi skarzi requested a review from sobolevn May 9, 2020 18:59
@skarzi skarzi self-assigned this May 9, 2020
@skarzi skarzi changed the title Issue 38 and 40 fix and refactor migrations test teardown and setup May 9, 2020
@codecov
Copy link

codecov bot commented May 9, 2020

Codecov Report

Merging #76 into master will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master       #76   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            5         9    +4     
  Lines          113       189   +76     
  Branches        13        19    +6     
=========================================
+ Hits           113       189   +76     
Impacted Files Coverage Δ
django_test_migrations/contrib/unittest_case.py 100.00% <100.00%> (ø)
django_test_migrations/exceptions.py 100.00% <100.00%> (ø)
django_test_migrations/logic/migrations.py 100.00% <100.00%> (ø)
django_test_migrations/migrator.py 100.00% <100.00%> (ø)
django_test_migrations/plan.py 100.00% <100.00%> (ø)
django_test_migrations/sql.py 100.00% <100.00%> (ø)
django_test_migrations/types.py 100.00% <100.00%> (ø)
... and 1 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update cbb8626...c3d0e6c. Read the comment docs.

Copy link
Member

@sobolevn sobolevn left a comment

Choose a reason for hiding this comment

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

Amazing work!

This is a very complicated feature, but a very simple and thoughtful implementation.
Really amazing 👍

However, there is some polishing to be done!

targets: List[MigrationTarget],
plan: MigrationPlan,
) -> MigrationPlan:
"""Truncate migrations ``plan`` up to ``targets``."""
Copy link
Member

Choose a reason for hiding this comment

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

Can you please add some more docs on why do we need this function.
It is not clear from the source code (at least for me).


_Connection = Union[DefaultConnectionProxy, BaseDatabaseWrapper]

DJANGO_MIGRATIONS_TABLE_NAME = 'django_migrations'
Copy link
Member

Choose a reason for hiding this comment

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

Should it be Final?

include_views=False,
)
sql_drop_tables = [
connection.SchemaEditorClass.sql_delete_table % {
Copy link
Member

Choose a reason for hiding this comment

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

Is this operation safe in terms of sql-injection? Maybe there are safer methods to join sql vars?

Should we even care?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It should be safe, because sql_delete_table is string format defined by database backend (no user input) and its table argument is table's name (not any users input again), so it should be save.
This implementation is based on https://github.com/django/django/blob/c226c6cb3209122b6732fd501e2994c408dc258e/django/db/backends/base/schema.py#L342

Copy link
Member

Choose a reason for hiding this comment

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

👍

database_name: str,
style: Optional[Style] = None,
) -> None:
"""Flush `django_migrations` table."""
Copy link
Member

Choose a reason for hiding this comment

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

Let's also explain why do we handle it separately.


This function is copy of ``connection.ops.execute_sql_flush``
method from Django's source code:
https://github.com/django/django/blob/227d0c7365cfd0a64d021cb9bdcf77bed2d3f170/django/db/backends/base/operations.py#L401
Copy link
Member

Choose a reason for hiding this comment

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

let's use bit.ly for this link.

method from Django's source code:
https://github.com/django/django/blob/227d0c7365cfd0a64d021cb9bdcf77bed2d3f170/django/db/backends/base/operations.py#L401
to make `django-test-migrations` compatible with `Django==1.11`.
``connection.ops.execute_sql_flush()`` was introduced in `Django==2.0`.
Copy link
Member

Choose a reason for hiding this comment

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

Django==2.0 should be in double backquotes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Surely I will correct it.
To be honest I don't feel the difference between single backquote and double backquotes.
I would be really grateful if you could explain it ;)



@pytest.fixture()
def plan(mocker):
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need a mocker here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

leftover from some "first attempts" code, thanks for catching!



def test_drop_models_table_table_detected(mocker):
"""Ensure `DROP TABLE` statements are executed when any table detected."""
Copy link
Member

Choose a reason for hiding this comment

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

Should be in double backquotes.



def test_drop_models_table_no_tables_detected(mocker):
"""Ensure any `DROP TABLE` statement executed when no tables detected."""
Copy link
Member

Choose a reason for hiding this comment

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

Should be in double backquotes.

Add more detailed docstrings.
Fix backquotes usage in docstrings.
Use bit.ly for long URLs.
Copy link
Member

@sobolevn sobolevn left a comment

Choose a reason for hiding this comment

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

Thanks a lot! Merging! 🎉

include_views=False,
)
sql_drop_tables = [
connection.SchemaEditorClass.sql_delete_table % {
Copy link
Member

Choose a reason for hiding this comment

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

👍

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.

properly apply migrations before running test properly reset databases on tests teardown
2 participants