You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
10 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. from django.core.exceptions import ValidationError
  2. from django.db.utils import IntegrityError
  3. from django.test import TestCase
  4. from model_mommy import mommy
  5. from ..models import (SEQUENCE_LABELING, Category, CategoryType, ExampleState,
  6. Span, SpanType, TextLabel, generate_random_hex_color)
  7. from .api.utils import prepare_project
  8. class TestLabel(TestCase):
  9. def test_deny_creating_same_text(self):
  10. label = mommy.make('CategoryType')
  11. with self.assertRaises(IntegrityError):
  12. mommy.make('CategoryType', project=label.project, text=label.text)
  13. def test_keys_uniqueness(self):
  14. label = mommy.make('CategoryType', prefix_key='ctrl', suffix_key='a')
  15. with self.assertRaises(ValidationError):
  16. CategoryType(project=label.project,
  17. text='example',
  18. prefix_key=label.prefix_key,
  19. suffix_key=label.suffix_key).full_clean()
  20. def test_suffix_key_uniqueness(self):
  21. label = mommy.make('CategoryType', prefix_key=None, suffix_key='a')
  22. with self.assertRaises(ValidationError):
  23. CategoryType(project=label.project,
  24. text='example',
  25. prefix_key=label.prefix_key,
  26. suffix_key=label.suffix_key).full_clean()
  27. def test_cannot_add_label_only_prefix_key(self):
  28. project = mommy.make('Project')
  29. label = CategoryType(project=project,
  30. text='example',
  31. prefix_key='ctrl')
  32. with self.assertRaises(ValidationError):
  33. label.clean()
  34. def test_can_add_label_only_suffix_key(self):
  35. project = mommy.make('Project')
  36. label = CategoryType(project=project, text='example', suffix_key='a')
  37. try:
  38. label.full_clean()
  39. except ValidationError:
  40. self.fail(msg=ValidationError)
  41. def test_can_add_label_suffix_key_with_prefix_key(self):
  42. project = mommy.make('Project')
  43. label = CategoryType(project=project,
  44. text='example',
  45. prefix_key='ctrl',
  46. suffix_key='a')
  47. try:
  48. label.full_clean()
  49. except ValidationError:
  50. self.fail(msg=ValidationError)
  51. class TestCategory(TestCase):
  52. def test_uniqueness(self):
  53. a = mommy.make('Category')
  54. with self.assertRaises(IntegrityError):
  55. Category(example=a.example, user=a.user, label=a.label).save()
  56. class TestSpan(TestCase):
  57. def setUp(self):
  58. self.project = prepare_project(SEQUENCE_LABELING, allow_overlapping=False)
  59. self.example = mommy.make('Example', project=self.project.item)
  60. self.user = self.project.users[0]
  61. def test_start_offset_is_not_negative(self):
  62. with self.assertRaises(IntegrityError):
  63. mommy.make('Span', start_offset=-1, end_offset=0)
  64. def test_end_offset_is_not_negative(self):
  65. with self.assertRaises(IntegrityError):
  66. mommy.make('Span', start_offset=-2, end_offset=-1)
  67. def test_start_offset_is_less_than_end_offset(self):
  68. with self.assertRaises(IntegrityError):
  69. mommy.make('Span', start_offset=0, end_offset=0)
  70. def test_unique_constraint(self):
  71. mommy.make('Span', example=self.example, start_offset=5, end_offset=10, user=self.user)
  72. mommy.make('Span', example=self.example, start_offset=0, end_offset=5, user=self.user)
  73. mommy.make('Span', example=self.example, start_offset=10, end_offset=15, user=self.user)
  74. def test_unique_constraint_violated(self):
  75. mommy.make('Span', example=self.example, start_offset=5, end_offset=10, user=self.user)
  76. spans = [(5, 10), (5, 11), (4, 10), (6, 9), (9, 15), (0, 6)]
  77. for start_offset, end_offset in spans:
  78. with self.assertRaises(ValidationError):
  79. mommy.make(
  80. 'Span',
  81. example=self.example,
  82. start_offset=start_offset,
  83. end_offset=end_offset,
  84. user=self.user
  85. )
  86. def test_unique_constraint_if_overlapping_is_allowed(self):
  87. project = prepare_project(SEQUENCE_LABELING, allow_overlapping=True)
  88. example = mommy.make('Example', project=project.item)
  89. user = project.users[0]
  90. mommy.make('Span', example=example, start_offset=5, end_offset=10, user=user)
  91. spans = [(5, 10), (5, 11), (4, 10), (6, 9), (9, 15), (0, 6)]
  92. for start_offset, end_offset in spans:
  93. mommy.make('Span', example=example, start_offset=start_offset, end_offset=end_offset, user=user)
  94. def test_update(self):
  95. span = mommy.make('Span', example=self.example, start_offset=0, end_offset=5)
  96. span.end_offset = 6
  97. span.save()
  98. class TestSpanWithoutCollaborativeMode(TestCase):
  99. def setUp(self):
  100. self.project = prepare_project(SEQUENCE_LABELING, False, allow_overlapping=False)
  101. self.example = mommy.make('Example', project=self.project.item)
  102. def test_allow_users_to_create_same_spans(self):
  103. mommy.make('Span', example=self.example, start_offset=5, end_offset=10, user=self.project.users[0])
  104. mommy.make('Span', example=self.example, start_offset=5, end_offset=10, user=self.project.users[1])
  105. class TestSpanWithCollaborativeMode(TestCase):
  106. def test_deny_users_to_create_same_spans(self):
  107. project = prepare_project(SEQUENCE_LABELING, True, allow_overlapping=False)
  108. example = mommy.make('Example', project=project.item)
  109. mommy.make('Span', example=example, start_offset=5, end_offset=10, user=project.users[0])
  110. with self.assertRaises(ValidationError):
  111. mommy.make('Span', example=example, start_offset=5, end_offset=10, user=project.users[1])
  112. def test_allow_users_to_create_same_spans_if_overlapping_is_allowed(self):
  113. project = prepare_project(SEQUENCE_LABELING, True, allow_overlapping=True)
  114. example = mommy.make('Example', project=project.item)
  115. mommy.make('Span', example=example, start_offset=5, end_offset=10, user=project.users[0])
  116. mommy.make('Span', example=example, start_offset=5, end_offset=10, user=project.users[1])
  117. class TestSeq2seqAnnotation(TestCase):
  118. def test_uniqueness(self):
  119. a = mommy.make('TextLabel')
  120. with self.assertRaises(IntegrityError):
  121. TextLabel(example=a.example,
  122. user=a.user,
  123. text=a.text).save()
  124. class TestGeneratedColor(TestCase):
  125. def test_length(self):
  126. for i in range(100):
  127. color = generate_random_hex_color()
  128. self.assertEqual(len(color), 7)
  129. class TestExampleState(TestCase):
  130. def setUp(self):
  131. self.project = prepare_project(SEQUENCE_LABELING)
  132. self.example = mommy.make('Example', project=self.project.item)
  133. self.other = mommy.make('Example', project=self.project.item)
  134. self.examples = self.project.item.examples.all()
  135. def test_initial_done(self):
  136. done = ExampleState.objects.count_done(self.examples)
  137. self.assertEqual(done, 0)
  138. def test_done_confirmed_by_user(self):
  139. mommy.make('ExampleState', example=self.example, confirmed_by=self.project.users[0])
  140. done = ExampleState.objects.count_done(self.examples)
  141. self.assertEqual(done, 1)
  142. def test_done_confirmed_by_multiple_user(self):
  143. mommy.make('ExampleState', example=self.example, confirmed_by=self.project.users[0])
  144. mommy.make('ExampleState', example=self.example, confirmed_by=self.project.users[1])
  145. done = ExampleState.objects.count_done(self.examples)
  146. self.assertEqual(done, 1)
  147. def test_done_confirmed_by_different_example(self):
  148. mommy.make('ExampleState', example=self.example, confirmed_by=self.project.users[0])
  149. mommy.make('ExampleState', example=self.other, confirmed_by=self.project.users[1])
  150. done = ExampleState.objects.count_done(self.examples, self.project.users[0])
  151. self.assertEqual(done, 1)
  152. def test_initial_user(self):
  153. progress = ExampleState.objects.measure_member_progress(self.examples, self.project.users)
  154. expected_progress = [{'user': user.username, 'done': 0} for user in self.project.users]
  155. self.assertEqual(progress, {'total': 2, 'progress': expected_progress})
  156. def test_user_count_after_confirmation(self):
  157. mommy.make('ExampleState', example=self.example, confirmed_by=self.project.users[0])
  158. progress = ExampleState.objects.measure_member_progress(self.examples, self.project.users)
  159. expected_progress = [{'user': user.username, 'done': 0} for user in self.project.users]
  160. expected_progress[0]['done'] = 1
  161. self.assertEqual(progress, {'total': 2, 'progress': expected_progress})
  162. def test_user_count_after_multiple_user_confirmation(self):
  163. user1 = self.project.users[0]
  164. user2 = self.project.users[1]
  165. mommy.make('ExampleState', example=self.example, confirmed_by=user1)
  166. mommy.make('ExampleState', example=self.example, confirmed_by=user2)
  167. progress = ExampleState.objects.measure_member_progress(self.examples, self.project.users)
  168. expected_progress = [{'user': user.username, 'done': 0} for user in self.project.users]
  169. expected_progress[0]['done'] = 1
  170. expected_progress[1]['done'] = 1
  171. self.assertEqual(progress, {'total': 2, 'progress': expected_progress})
  172. class TestLabelDistribution(TestCase):
  173. def setUp(self):
  174. self.project = prepare_project(SEQUENCE_LABELING, allow_overlapping=False)
  175. self.example = mommy.make('Example', project=self.project.item)
  176. self.user = self.project.users[0]
  177. def test_calc_label_distribution(self):
  178. label_a = mommy.make('SpanType', text='labelA', project=self.project.item)
  179. label_b = mommy.make('SpanType', text='labelB', project=self.project.item)
  180. mommy.make('Span', example=self.example, start_offset=5, end_offset=10, user=self.user, label=label_a)
  181. mommy.make('Span', example=self.example, start_offset=10, end_offset=15, user=self.user, label=label_b)
  182. distribution = Span.objects.calc_label_distribution(
  183. examples=self.project.item.examples.all(),
  184. users=self.project.item.users.all(),
  185. labels=SpanType.objects.all()
  186. )
  187. expected = {user.username: {label.text: 0 for label in SpanType.objects.all()} for user in self.project.users}
  188. expected[self.user.username][label_a.text] = 1
  189. expected[self.user.username][label_b.text] = 1
  190. self.assertEqual(distribution, expected)