Ensure UnitTest coverage at least 85% #16

Closed
opened 2025-04-23 12:26:12 +00:00 by stanislav.hejny · 3 comments

Ref epic: CleverSwarm Onboarding #58

Ensure proper unit test coverage, currently test coverage is 42%

Ref epic: [CleverSwarm Onboarding #58](https://git.cleverthis.com/clevermicro/clevermicro/issues/58) Ensure proper unit test coverage, currently test coverage is 42%
Owner

@stanislav.hejny @aleenaumair

This ticket is also lacking priority (which needs to be set to backlog) as well as a milestone. Make sure this is fixed before moving forward. I MoSCoWed it though generally that would wait until the ticket is complete.

@stanislav.hejny @aleenaumair This ticket is also lacking priority (which needs to be set to backlog) as well as a milestone. Make sure this is fixed before moving forward. I MoSCoWed it though generally that would wait until the ticket is complete.
aleenaumair added this to the V.01 milestone 2025-05-05 10:04:11 +00:00
Member

Hi,
Just want to reference a previous conversation around this, for documenting it; we discussed how setting Priority: Backlog overrides the Priority:High/ Med/ Low. So, until 'Backlog' gets moved to 'Status' label, we will be assigning high/med/low priority and keeping state 'unverified/verified' to depict tickets that are not 'In Progress' yet, meaning that they are still part of the backlog.
Please let us know as soon as the Backlog label is moved to status queue, so that we can start adding that to the tickets. @freemo

In addition, the 'Type' label also needs editing, to differentiate type (task, epic and legendary) and category (bug, feature, config, documentation, support, discussion).
cc: @eugen.thaci

Hi, Just want to reference a previous conversation around this, for documenting it; we discussed how setting Priority: Backlog overrides the Priority:High/ Med/ Low. So, until 'Backlog' gets moved to 'Status' label, we will be assigning high/med/low priority and keeping state 'unverified/verified' to depict tickets that are not 'In Progress' yet, meaning that they are still part of the backlog. Please let us know as soon as the Backlog label is moved to status queue, so that we can start adding that to the tickets. @freemo In addition, the 'Type' label also needs editing, to differentiate type (task, epic and legendary) and category (bug, feature, config, documentation, support, discussion). cc: @eugen.thaci
stanislav.hejny was assigned by hurui200320 2025-05-12 06:01:14 +00:00
Member

Currently, Stan and I are working on the unit test. The estimated points are 8, but it actually taking much longer than it. In theory, writing unit tests should be easy since all the features are implemented, and all you need to do is to write code to ensure the functionality of them. But in reality, bugs may be found and refactor may be required for easy testing.

In today's case, I'm writing unit tests for amqp/adapter/pydantic_serializer.py. As suggested by Aleena, I downloaded cursor ai editor and started generating unit tests (currently with a free 7-day trial). Generating unit test is fast, review the generated code is also not hard, everything looks good to me. At this point, including download, it takes less than 5 minutes. For the rest of the day, I'm fixing the code so the unit test can pass.

I run the unit test, it failed, I start fixing it. The first problem is related to how python finds classes. For the pydantic serializer, we need to know the class before we deserialize it. The code records the class name before the actual data so we know which class to use when deserializing. However, in python, a class name is not enough to locate a class, you also need a module path. This is relatively easy to fix since llm gives me the correct code to do that.

I rerun the test again, now the deserialization is failing, due to broken data. I added several print statements to see what data is being fed to the method, and noticed an issue with serialization. The serializer uses comma to separate key value pairs, which is generally fine until your value can also contain comma. For example, dict and list. When deserializing, the input string will be split by comma, this will break dick and list, causing an error. I fixed it by using JSON.

I rerun the test again, and got a new error. But now the error is triggered by the test code, saying a field should be an object, but after deserialization, it becomes a dict. In the serializer, I saw code that handles the nested model specifically, but it doesn't run. After some debugging, I found the issue caused by obj.model_dump(). This pydantic method will export the model, but turning everything into dict. In this process, nested models will be also converted to dict, making the code failed to check if it's a nested model or not. By not using the converted value, we can pull the original value using the field name, and continue the process. However, in the deserializer, the input string doesn't give anything about the type, so we need to look up the type in the class. This is where the llm doesn't help: with python 3.9, you have an old way to do that; with python 3.10, you have a new way to do that. And with pydantic v1 and v2, there are also different APIs. LLM's output failed to keep up to date, and I spend a bunch of time to figure out how python's type system working, how pydantic helps on that, and the most time-consuming part, how to handle union type like Foo | None.

At the end of the day, everything is fixed and the coverage for that file is 89%, and the overall coverage rate is bumped by 3%. But this process takes me a whole day, largely due to my unfamiliarity with python and related library. I expect this should be improved as I keep working on the codebase and gain more and more experience with python, the codebase and related libraries.

Currently, Stan and I are working on the unit test. The estimated points are 8, but it actually taking much longer than it. In theory, writing unit tests should be easy since all the features are implemented, and all you need to do is to write code to ensure the functionality of them. But in reality, bugs may be found and refactor may be required for easy testing. In today's case, I'm writing unit tests for `amqp/adapter/pydantic_serializer.py`. As suggested by Aleena, I downloaded cursor ai editor and started generating unit tests (currently with a free 7-day trial). Generating unit test is fast, review the generated code is also not hard, everything looks good to me. At this point, including download, it takes less than 5 minutes. For the rest of the day, I'm fixing the code so the unit test can pass. I run the unit test, it failed, I start fixing it. The first problem is related to how python finds classes. For the pydantic serializer, we need to know the class before we deserialize it. The code records the class name before the actual data so we know which class to use when deserializing. However, in python, a class name is not enough to locate a class, you also need a module path. This is relatively easy to fix since llm gives me the correct code to do that. I rerun the test again, now the deserialization is failing, due to broken data. I added several print statements to see what data is being fed to the method, and noticed an issue with serialization. The serializer uses comma to separate key value pairs, which is generally fine until your value can also contain comma. For example, dict and list. When deserializing, the input string will be split by comma, this will break dick and list, causing an error. I fixed it by using JSON. I rerun the test again, and got a new error. But now the error is triggered by the test code, saying a field should be an object, but after deserialization, it becomes a dict. In the serializer, I saw code that handles the nested model specifically, but it doesn't run. After some debugging, I found the issue caused by `obj.model_dump()`. This pydantic method will export the model, but turning everything into dict. In this process, nested models will be also converted to dict, making the code failed to check if it's a nested model or not. By not using the converted value, we can pull the original value using the field name, and continue the process. However, in the deserializer, the input string doesn't give anything about the type, so we need to look up the type in the class. This is where the llm doesn't help: with python 3.9, you have an old way to do that; with python 3.10, you have a new way to do that. And with pydantic v1 and v2, there are also different APIs. LLM's output failed to keep up to date, and I spend a bunch of time to figure out how python's type system working, how pydantic helps on that, and the most time-consuming part, how to handle union type like `Foo | None`. At the end of the day, everything is fixed and the coverage for that file is 89%, and the overall coverage rate is bumped by 3%. But this process takes me a whole day, largely due to my unfamiliarity with python and related library. I expect this should be improved as I keep working on the codebase and gain more and more experience with python, the codebase and related libraries.
Sign in to join this conversation.
No milestone
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
You do not have permission to read 2 dependencies
Depends on
#47 Implement unit test
clevermicro/amq-adapter-python
Reference: clevermicro/amq-adapter-python#16
No description provided.