Coverage for tests/test_computed_fields.py: 100%

37 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-12-04 08:29 +0000

1import pytest 1abcdefg

2from fastapi import FastAPI 1abcdefg

3from fastapi.testclient import TestClient 1abcdefg

4 

5from .utils import needs_pydanticv2 1abcdefg

6 

7 

8@pytest.fixture(name="client") 1abcdefg

9def get_client(request): 1abcdefg

10 separate_input_output_schemas = request.param 1abcdefg

11 app = FastAPI(separate_input_output_schemas=separate_input_output_schemas) 1abcdefg

12 

13 from pydantic import BaseModel, computed_field 1abcdefg

14 

15 class Rectangle(BaseModel): 1abcdefg

16 width: int 1abcdefg

17 length: int 1abcdefg

18 

19 @computed_field 1abcdefg

20 @property 1abcdefg

21 def area(self) -> int: 1abcdefg

22 return self.width * self.length 1hijklmn

23 

24 @app.get("/") 1abcdefg

25 def read_root() -> Rectangle: 1abcdefg

26 return Rectangle(width=3, length=4) 1hijklmn

27 

28 @app.get("/responses", responses={200: {"model": Rectangle}}) 1abcdefg

29 def read_responses() -> Rectangle: 1abcdefg

30 return Rectangle(width=3, length=4) 1hijklmn

31 

32 client = TestClient(app) 1abcdefg

33 return client 1abcdefg

34 

35 

36@pytest.mark.parametrize("client", [True, False], indirect=True) 1abcdefg

37@pytest.mark.parametrize("path", ["/", "/responses"]) 1abcdefg

38@needs_pydanticv2 1abcdefg

39def test_get(client: TestClient, path: str): 1abcdefg

40 response = client.get(path) 1hijklmn

41 assert response.status_code == 200, response.text 1hijklmn

42 assert response.json() == {"width": 3, "length": 4, "area": 12} 1hijklmn

43 

44 

45@pytest.mark.parametrize("client", [True, False], indirect=True) 1abcdefg

46@needs_pydanticv2 1abcdefg

47def test_openapi_schema(client: TestClient): 1abcdefg

48 response = client.get("/openapi.json") 1opqrstu

49 assert response.status_code == 200, response.text 1opqrstu

50 assert response.json() == { 1opqrstu

51 "openapi": "3.1.0", 

52 "info": {"title": "FastAPI", "version": "0.1.0"}, 

53 "paths": { 

54 "/": { 

55 "get": { 

56 "summary": "Read Root", 

57 "operationId": "read_root__get", 

58 "responses": { 

59 "200": { 

60 "description": "Successful Response", 

61 "content": { 

62 "application/json": { 

63 "schema": {"$ref": "#/components/schemas/Rectangle"} 

64 } 

65 }, 

66 } 

67 }, 

68 } 

69 }, 

70 "/responses": { 

71 "get": { 

72 "summary": "Read Responses", 

73 "operationId": "read_responses_responses_get", 

74 "responses": { 

75 "200": { 

76 "description": "Successful Response", 

77 "content": { 

78 "application/json": { 

79 "schema": {"$ref": "#/components/schemas/Rectangle"} 

80 } 

81 }, 

82 } 

83 }, 

84 } 

85 }, 

86 }, 

87 "components": { 

88 "schemas": { 

89 "Rectangle": { 

90 "properties": { 

91 "width": {"type": "integer", "title": "Width"}, 

92 "length": {"type": "integer", "title": "Length"}, 

93 "area": {"type": "integer", "title": "Area", "readOnly": True}, 

94 }, 

95 "type": "object", 

96 "required": ["width", "length", "area"], 

97 "title": "Rectangle", 

98 } 

99 } 

100 }, 

101 }