Coverage for /Users/davegaeddert/Development/dropseed/plain/plain-models/plain/models/test/pytest.py: 95%

42 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-10-16 22:04 -0500

1import pytest 

2 

3from plain.signals import request_finished, request_started 

4 

5from .. import transaction 

6from ..backends.base.base import BaseDatabaseWrapper 

7from ..db import close_old_connections, connections 

8from .utils import ( 

9 setup_databases, 

10 teardown_databases, 

11) 

12 

13 

14@pytest.fixture(autouse=True) 

15def _db_disabled(): 

16 """ 

17 Every test should use this fixture by default to prevent 

18 access to the normal database. 

19 """ 

20 

21 def cursor_disabled(self): 

22 pytest.fail("Database access not allowed without the `db` fixture") 

23 

24 BaseDatabaseWrapper._old_cursor = BaseDatabaseWrapper.cursor 

25 BaseDatabaseWrapper.cursor = cursor_disabled 

26 

27 yield 

28 

29 BaseDatabaseWrapper.cursor = BaseDatabaseWrapper._old_cursor 

30 

31 

32@pytest.fixture(scope="session") 

33def setup_db(request): 

34 """ 

35 This fixture is called automatically by `db`, 

36 so a test database will only be setup if the `db` fixture is used. 

37 """ 

38 verbosity = request.config.option.verbose 

39 

40 # Set up the test db across the entire session 

41 _old_db_config = setup_databases(verbosity=verbosity) 

42 

43 # Keep connections open during request client / testing 

44 request_started.disconnect(close_old_connections) 

45 request_finished.disconnect(close_old_connections) 

46 

47 yield _old_db_config 

48 

49 # Put the signals back... 

50 request_started.connect(close_old_connections) 

51 request_finished.connect(close_old_connections) 

52 

53 # When the test session is done, tear down the test db 

54 teardown_databases(_old_db_config, verbosity=verbosity) 

55 

56 

57@pytest.fixture() 

58def db(setup_db): 

59 # Set .cursor() back to the original implementation 

60 BaseDatabaseWrapper.cursor = BaseDatabaseWrapper._old_cursor 

61 

62 # Keep track of the atomic blocks so we can roll them back 

63 atomics = {} 

64 

65 for connection in connections.all(): 

66 # By default we use transactions to rollback changes, 

67 # so we need to ensure the database supports transactions 

68 if not connection.features.supports_transactions: 

69 pytest.fail("Database does not support transactions") 

70 

71 # Clear the queries log before each test? 

72 # connection.queries_log.clear() 

73 

74 atomic = transaction.atomic(using=connection.alias) 

75 atomic._from_testcase = True # TODO remove this somehow? 

76 atomic.__enter__() 

77 atomics[connection] = atomic 

78 

79 yield setup_db 

80 

81 for connection, atomic in atomics.items(): 

82 if ( 

83 connection.features.can_defer_constraint_checks 

84 and not connection.needs_rollback 

85 and connection.is_usable() 

86 ): 

87 connection.check_constraints() 

88 

89 transaction.set_rollback(True, using=connection.alias) 

90 atomic.__exit__(None, None, None) 

91 

92 connection.close() 

93 

94 

95# @pytest.fixture(scope="function") 

96# def transactional_db(request, _plain_db_setup): 

97# BaseDatabaseWrapper.cursor = BaseDatabaseWrapper._cursor 

98 

99# yield 

100 

101# # Flush databases instead of rolling back transactions... 

102 

103# connections.close_all()