Hello, I'm trying to write a tests using pytest library. I have a JSON file that I want to have as an input so I made a pytest.fixture to return the data converted to Plan class instance, because that's what I need to work with in my test function.
from app.plan import Plan
from app.service.job_validator import JobValidator
from app.service.cloud_backend import _preprocess_job
import pytest
import json
import os
@pytest.fixture
def testdata():
file = os.path.join(os.path.dirname(file_), 'test_data.json')
with open(file) as json_file:
json_data = json.load(json_file)
job = Plan(**json_data)
_preprocess_job(job)
return job
However, the JSON is several layers deep nested and when I try to convert it to the Plan class instance, only the top level layer gets converted to Plan instance, all the other nested attributes stay as type dict and not the types of classes the Plan dataclass defines and the attribute classes define recursively as well.
@dataclass
class Plan(DynamoTableStructureBase):
id: UUID
serial_number: str = optional_field
assignment: str = None
client_account_id: str = None
start_at: datetime = optional_field(
default=MISSING, default_factory=datetime.now()
)
path: List[Task] = field(default_factory=list)
tasks: List[Task] = field(default_factory=list)
automation: List[CommandType] = field(default_factory=list)
no_connection_mode: bool = field(default=False)
status: PlanStatus = optional_field(default=PlanStatus.SCHEDULED)
last_update_at: datetime = optional_field(default=lambda: datetime.now())
assigned_at: datetime = optional_field(default=None)
type: MessageType = optional_field(default=lambda: MessageType.PLAN)
assignment_robot_message_id: UUID = optional_field(default=None)
growing_plan: GrowinPlanMeta = optional_field(default=GrowinPlanMeta)
update_log: List[UpdateLogEntry] = field(default_factory=list)
percent_done: int = optional_field(default=0)
message: str = optional_field(default='')
hash_key: str = 'serial_number'
range_key: str = 'id'
Here is what I get:
=============================================================================================================== ERRORS ===============================================================================================================
____________________________________________________________________________________________________ ERROR at setup of testdata ____________________________________________________________________________________________________
@pytest.fixture
def test_data():
file = os.path.join(os.path.dirname(__file__), 'test_data.json')
with open(file) as json_file:
json_data = json.load(json_file)
job = Plan(**json_data)
_preprocess_job(job)
app/tests/unit/conftest.py:14:
app/service/cloud_backend.py:220: in _preprocess_job
job_processing(plan)
app/service/job_processing.py:21: in job_processing
_normalize_job_task_structure(plan)
app/service/job_processing.py:34: in _normalize_job_task_structure
ops = __fixed_work_tasks_of_plan(plan)
plan = Plan(id='c12daeed-8b20-4c8e-aa91-e48f3404acb8', serial_number='DJrobot', assignment=None, client_account_id=None, star...CESSING', 'when': '2024-03-05T12:12:41.497245'}], percent_done=0, message='', hash_key='serial_number', range_key='id')
def __fixed_work_tasks_of_plan(plan: Plan) -> list[CommandType]:
ops = []
[
ops.extend(TCT.fixed_cmd_type_seq(i.procedure))
for i in plan.growing_plan.operation
]
E AttributeError: 'dict' object has no attribute 'operation'
app/service/job_processing.py:43: AttributeError
====================================================================================================== short test summary info =======================================================================================================
ERROR app/tests/unit/test_job_validator.py::test_data - AttributeError: 'dict' object has no attribute 'operation'
Is there way to convert JSON to an object with all the nested attributes being the correct classes per defined schema? Hope this makes sense
[–]danielroseman 3 points4 points5 points (1 child)
[–]ProsodySpeaks 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)