Skip to content

Commit 5eef98a

Browse files
committed
[ADD] comprehensive tests for queue job tracking in demo data generator
1 parent 1868f51 commit 5eef98a

File tree

2 files changed

+347
-0
lines changed

2 files changed

+347
-0
lines changed

spp_demo_common/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
## 2025-11-20
44

5+
### 2025-11-20 16:15:00 - [ADD] comprehensive tests for queue job tracking in demo data generator
6+
7+
- Added test_28: Tests `_compute_queue_job_ids` correctly filters jobs by generator record
8+
- Added test_29: Tests `queue_job_count` computation
9+
- Added test_30: Tests `has_ongoing_jobs` with no jobs
10+
- Added test_31: Tests detection of pending jobs
11+
- Added test_32: Tests detection of enqueued jobs
12+
- Added test_33: Tests detection of started jobs
13+
- Added test_34: Tests that completed jobs don't trigger ongoing flag
14+
- Added test_35: Tests cross-record behavior - ongoing jobs affect all generator records
15+
- Added test_36: Tests mixed job states scenario
16+
- Added test_37: Tests model isolation - jobs from other models don't affect demo generator
17+
- Total 10 new tests providing comprehensive coverage for queue job tracking functionality
18+
519
### 2025-11-20 15:45:00 - [IMP] enhance queue job tracking and prevent concurrent operations
620

721
- Added `has_ongoing_jobs` computed field to detect concurrent job operations

spp_demo_common/tests/test_demo_data_generator.py

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,3 +624,336 @@ def test_27_edge_case_regex_generation_complex(self):
624624
result2 = generator.generate_id_from_regex(pattern2)
625625
self.assertIsNotNone(result2)
626626
self.assertEqual(len(result2), 5)
627+
628+
def test_28_compute_queue_job_ids(self):
629+
"""Test that generator correctly computes related queue jobs"""
630+
generator1 = self.env["spp.demo.data.generator"].create(
631+
{
632+
"name": "Generator with Jobs",
633+
"locale_origin": self.test_country.id,
634+
}
635+
)
636+
generator2 = self.env["spp.demo.data.generator"].create(
637+
{
638+
"name": "Generator without Jobs",
639+
"locale_origin": self.test_country.id,
640+
}
641+
)
642+
643+
# Create jobs for generator1
644+
job1 = self.env["queue.job"].create(
645+
{
646+
"name": "Job 1 for Generator 1",
647+
"model_name": "spp.demo.data.generator",
648+
"method_name": "_process_batch",
649+
"res_model": "spp.demo.data.generator",
650+
"res_id": generator1.id,
651+
"state": "done",
652+
}
653+
)
654+
job2 = self.env["queue.job"].create(
655+
{
656+
"name": "Job 2 for Generator 1",
657+
"model_name": "spp.demo.data.generator",
658+
"method_name": "_process_batch",
659+
"res_model": "spp.demo.data.generator",
660+
"res_id": generator1.id,
661+
"state": "pending",
662+
}
663+
)
664+
665+
# Trigger compute
666+
generator1._compute_queue_job_ids()
667+
generator2._compute_queue_job_ids()
668+
669+
# Assert generator1 has 2 jobs
670+
self.assertEqual(len(generator1.queue_job_ids), 2)
671+
self.assertIn(job1, generator1.queue_job_ids)
672+
self.assertIn(job2, generator1.queue_job_ids)
673+
674+
# Assert generator2 has no jobs
675+
self.assertEqual(len(generator2.queue_job_ids), 0)
676+
677+
def test_29_compute_queue_job_count(self):
678+
"""Test queue job count computation"""
679+
generator = self.env["spp.demo.data.generator"].create(
680+
{
681+
"name": "Generator for Count Test",
682+
"locale_origin": self.test_country.id,
683+
}
684+
)
685+
686+
# Initially no jobs
687+
generator._compute_queue_job_ids()
688+
generator._compute_queue_job_count()
689+
self.assertEqual(generator.queue_job_count, 0)
690+
691+
# Create 3 jobs
692+
for i in range(3):
693+
self.env["queue.job"].create(
694+
{
695+
"name": f"Job {i+1}",
696+
"model_name": "spp.demo.data.generator",
697+
"method_name": "_process_batch",
698+
"res_model": "spp.demo.data.generator",
699+
"res_id": generator.id,
700+
"state": "done",
701+
}
702+
)
703+
704+
# Recompute
705+
generator._compute_queue_job_ids()
706+
generator._compute_queue_job_count()
707+
self.assertEqual(generator.queue_job_count, 3)
708+
709+
def test_30_has_ongoing_jobs_no_jobs(self):
710+
"""Test has_ongoing_jobs when there are no jobs"""
711+
# Clean up any existing jobs
712+
self.env["queue.job"].search([("res_model", "=", "spp.demo.data.generator")]).unlink()
713+
714+
generator = self.env["spp.demo.data.generator"].create(
715+
{
716+
"name": "Generator No Jobs",
717+
"locale_origin": self.test_country.id,
718+
}
719+
)
720+
721+
generator._compute_ongoing_jobs_info()
722+
self.assertFalse(generator.has_ongoing_jobs)
723+
self.assertFalse(generator.ongoing_job_generator_id)
724+
725+
def test_31_has_ongoing_jobs_with_pending_job(self):
726+
"""Test has_ongoing_jobs detects pending jobs"""
727+
# Clean up any existing jobs
728+
self.env["queue.job"].search([("res_model", "=", "spp.demo.data.generator")]).unlink()
729+
730+
generator = self.env["spp.demo.data.generator"].create(
731+
{
732+
"name": "Generator with Pending Job",
733+
"locale_origin": self.test_country.id,
734+
}
735+
)
736+
737+
# Create a pending job
738+
self.env["queue.job"].create(
739+
{
740+
"name": "Pending Job",
741+
"model_name": "spp.demo.data.generator",
742+
"method_name": "_process_batch",
743+
"res_model": "spp.demo.data.generator",
744+
"res_id": generator.id,
745+
"state": "pending",
746+
}
747+
)
748+
749+
generator._compute_ongoing_jobs_info()
750+
self.assertTrue(generator.has_ongoing_jobs)
751+
self.assertEqual(generator.ongoing_job_generator_id, generator)
752+
753+
def test_32_has_ongoing_jobs_with_enqueued_job(self):
754+
"""Test has_ongoing_jobs detects enqueued jobs"""
755+
# Clean up any existing jobs
756+
self.env["queue.job"].search([("res_model", "=", "spp.demo.data.generator")]).unlink()
757+
758+
generator = self.env["spp.demo.data.generator"].create(
759+
{
760+
"name": "Generator with Enqueued Job",
761+
"locale_origin": self.test_country.id,
762+
}
763+
)
764+
765+
# Create an enqueued job
766+
self.env["queue.job"].create(
767+
{
768+
"name": "Enqueued Job",
769+
"model_name": "spp.demo.data.generator",
770+
"method_name": "_process_batch",
771+
"res_model": "spp.demo.data.generator",
772+
"res_id": generator.id,
773+
"state": "enqueued",
774+
}
775+
)
776+
777+
generator._compute_ongoing_jobs_info()
778+
self.assertTrue(generator.has_ongoing_jobs)
779+
self.assertEqual(generator.ongoing_job_generator_id, generator)
780+
781+
def test_33_has_ongoing_jobs_with_started_job(self):
782+
"""Test has_ongoing_jobs detects started jobs"""
783+
# Clean up any existing jobs
784+
self.env["queue.job"].search([("res_model", "=", "spp.demo.data.generator")]).unlink()
785+
786+
generator = self.env["spp.demo.data.generator"].create(
787+
{
788+
"name": "Generator with Started Job",
789+
"locale_origin": self.test_country.id,
790+
}
791+
)
792+
793+
# Create a started job
794+
self.env["queue.job"].create(
795+
{
796+
"name": "Started Job",
797+
"model_name": "spp.demo.data.generator",
798+
"method_name": "_process_batch",
799+
"res_model": "spp.demo.data.generator",
800+
"res_id": generator.id,
801+
"state": "started",
802+
}
803+
)
804+
805+
generator._compute_ongoing_jobs_info()
806+
self.assertTrue(generator.has_ongoing_jobs)
807+
self.assertEqual(generator.ongoing_job_generator_id, generator)
808+
809+
def test_34_has_ongoing_jobs_with_done_job(self):
810+
"""Test has_ongoing_jobs with completed jobs"""
811+
# Clean up any existing jobs
812+
self.env["queue.job"].search([("res_model", "=", "spp.demo.data.generator")]).unlink()
813+
814+
generator = self.env["spp.demo.data.generator"].create(
815+
{
816+
"name": "Generator with Done Job",
817+
"locale_origin": self.test_country.id,
818+
}
819+
)
820+
821+
# Create only done jobs
822+
self.env["queue.job"].create(
823+
{
824+
"name": "Done Job",
825+
"model_name": "spp.demo.data.generator",
826+
"method_name": "_process_batch",
827+
"res_model": "spp.demo.data.generator",
828+
"res_id": generator.id,
829+
"state": "done",
830+
}
831+
)
832+
833+
generator._compute_ongoing_jobs_info()
834+
self.assertFalse(generator.has_ongoing_jobs)
835+
self.assertFalse(generator.ongoing_job_generator_id)
836+
837+
def test_35_has_ongoing_jobs_cross_record(self):
838+
"""Test has_ongoing_jobs affects all records when any generator has ongoing jobs"""
839+
# Clean up any existing jobs
840+
self.env["queue.job"].search([("res_model", "=", "spp.demo.data.generator")]).unlink()
841+
842+
generator1 = self.env["spp.demo.data.generator"].create(
843+
{
844+
"name": "Generator 1",
845+
"locale_origin": self.test_country.id,
846+
}
847+
)
848+
generator2 = self.env["spp.demo.data.generator"].create(
849+
{
850+
"name": "Generator 2",
851+
"locale_origin": self.test_country.id,
852+
}
853+
)
854+
855+
# Create a pending job for generator1 only
856+
self.env["queue.job"].create(
857+
{
858+
"name": "Pending Job for Generator 1",
859+
"model_name": "spp.demo.data.generator",
860+
"method_name": "_process_batch",
861+
"res_model": "spp.demo.data.generator",
862+
"res_id": generator1.id,
863+
"state": "pending",
864+
}
865+
)
866+
867+
# Trigger compute on both
868+
generator1._compute_ongoing_jobs_info()
869+
generator2._compute_ongoing_jobs_info()
870+
871+
# Both should show has_ongoing_jobs = True
872+
self.assertTrue(generator1.has_ongoing_jobs)
873+
self.assertTrue(generator2.has_ongoing_jobs)
874+
875+
# Both should point to generator1 as the one with ongoing jobs
876+
self.assertEqual(generator1.ongoing_job_generator_id, generator1)
877+
self.assertEqual(generator2.ongoing_job_generator_id, generator1)
878+
879+
def test_36_has_ongoing_jobs_mixed_states(self):
880+
"""Test has_ongoing_jobs with mixed job states"""
881+
# Clean up any existing jobs
882+
self.env["queue.job"].search([("res_model", "=", "spp.demo.data.generator")]).unlink()
883+
884+
generator = self.env["spp.demo.data.generator"].create(
885+
{
886+
"name": "Generator Mixed States",
887+
"locale_origin": self.test_country.id,
888+
}
889+
)
890+
891+
# Create jobs with different states
892+
self.env["queue.job"].create(
893+
{
894+
"name": "Done Job",
895+
"model_name": "spp.demo.data.generator",
896+
"method_name": "_process_batch",
897+
"res_model": "spp.demo.data.generator",
898+
"res_id": generator.id,
899+
"state": "done",
900+
}
901+
)
902+
self.env["queue.job"].create(
903+
{
904+
"name": "Failed Job",
905+
"model_name": "spp.demo.data.generator",
906+
"method_name": "_process_batch",
907+
"res_model": "spp.demo.data.generator",
908+
"res_id": generator.id,
909+
"state": "failed",
910+
}
911+
)
912+
self.env["queue.job"].create(
913+
{
914+
"name": "Pending Job",
915+
"model_name": "spp.demo.data.generator",
916+
"method_name": "_process_batch",
917+
"res_model": "spp.demo.data.generator",
918+
"res_id": generator.id,
919+
"state": "pending",
920+
}
921+
)
922+
923+
generator._compute_ongoing_jobs_info()
924+
925+
# Should be True because there's one pending job
926+
self.assertTrue(generator.has_ongoing_jobs)
927+
self.assertEqual(generator.ongoing_job_generator_id, generator)
928+
929+
def test_37_queue_job_isolation_from_other_models(self):
930+
"""Test that jobs from other models don't affect demo generator"""
931+
# Clean up any existing jobs
932+
self.env["queue.job"].search([("res_model", "=", "spp.demo.data.generator")]).unlink()
933+
934+
generator = self.env["spp.demo.data.generator"].create(
935+
{
936+
"name": "Generator Isolation Test",
937+
"locale_origin": self.test_country.id,
938+
}
939+
)
940+
941+
# Create a pending job for a different model
942+
self.env["queue.job"].create(
943+
{
944+
"name": "Job for different model",
945+
"model_name": "res.partner",
946+
"method_name": "test_method",
947+
"res_model": "res.partner",
948+
"res_id": 1,
949+
"state": "pending",
950+
}
951+
)
952+
953+
generator._compute_ongoing_jobs_info()
954+
generator._compute_queue_job_ids()
955+
956+
# Should not be affected by jobs from other models
957+
self.assertFalse(generator.has_ongoing_jobs)
958+
self.assertFalse(generator.ongoing_job_generator_id)
959+
self.assertEqual(len(generator.queue_job_ids), 0)

0 commit comments

Comments
 (0)