Coverage for tests / test_tutorial / test_fastapi / test_multiple_models / test_tutorial001.py: 100%

45 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-11-09 00:02 +0000

1import importlib 1jklmnopqr

2from types import ModuleType 1jklmnopqr

3 

4import pytest 1jklmnopqr

5from dirty_equals import IsOneOf 1jklmnopqr

6from fastapi.testclient import TestClient 1jklmnopqr

7from sqlalchemy import Engine, inspect 1jklmnopqr

8from sqlalchemy.engine.reflection import Inspector 1jklmnopqr

9 

10 

11@pytest.fixture( 1jklmnopqr

12 name="module", 

13 params=[ 

14 pytest.param("tutorial001_py310"), 

15 ], 

16) 

17def get_module(request: pytest.FixtureRequest, database_engine: Engine) -> ModuleType: 1jklmnopqr

18 mod = importlib.import_module( 1jklmnopqr

19 f"docs_src.tutorial.fastapi.multiple_models.{request.param}" 

20 ) 

21 mod.engine = database_engine 1jklmnopqr

22 return mod 1jklmnopqr

23 

24 

25def test_tutorial(module: ModuleType): 1jklmnopqr

26 with TestClient(module.app) as client: 1abcdefghi

27 hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} 1abcdefghi

28 hero2_data = { 1abcdefghi

29 "name": "Spider-Boy", 

30 "secret_name": "Pedro Parqueador", 

31 "id": 9000, 

32 } 

33 response = client.post("/heroes/", json=hero1_data) 1abcdefghi

34 data = response.json() 1abcdefghi

35 

36 assert response.status_code == 200, response.text 1abcdefghi

37 assert data["name"] == hero1_data["name"] 1abcdefghi

38 assert data["secret_name"] == hero1_data["secret_name"] 1abcdefghi

39 assert data["id"] is not None 1abcdefghi

40 assert data["age"] is None 1abcdefghi

41 

42 response = client.post("/heroes/", json=hero2_data) 1abcdefghi

43 data = response.json() 1abcdefghi

44 

45 assert response.status_code == 200, response.text 1abcdefghi

46 assert data["name"] == hero2_data["name"] 1abcdefghi

47 assert data["secret_name"] == hero2_data["secret_name"] 1abcdefghi

48 assert data["id"] != hero2_data["id"], ( 1abcdefghi

49 "Now it's not possible to predefine the ID from the request, " 

50 "it's now set by the database" 

51 ) 

52 assert data["age"] is None 1abcdefghi

53 

54 response = client.get("/heroes/") 1abcdefghi

55 data = response.json() 1abcdefghi

56 

57 assert response.status_code == 200, response.text 1abcdefghi

58 assert len(data) == 2 1abcdefghi

59 assert data[0]["name"] == hero1_data["name"] 1abcdefghi

60 assert data[0]["secret_name"] == hero1_data["secret_name"] 1abcdefghi

61 assert data[1]["name"] == hero2_data["name"] 1abcdefghi

62 assert data[1]["secret_name"] == hero2_data["secret_name"] 1abcdefghi

63 assert data[1]["id"] != hero2_data["id"] 1abcdefghi

64 

65 response = client.get("/openapi.json") 1abcdefghi

66 

67 assert response.status_code == 200, response.text 1abcdefghi

68 

69 assert response.json() == { 1abcdefghi

70 "openapi": "3.1.0", 

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

72 "paths": { 

73 "/heroes/": { 

74 "get": { 

75 "summary": "Read Heroes", 

76 "operationId": "read_heroes_heroes__get", 

77 "responses": { 

78 "200": { 

79 "description": "Successful Response", 

80 "content": { 

81 "application/json": { 

82 "schema": { 

83 "title": "Response Read Heroes Heroes Get", 

84 "type": "array", 

85 "items": { 

86 "$ref": "#/components/schemas/HeroPublic" 

87 }, 

88 } 

89 } 

90 }, 

91 } 

92 }, 

93 }, 

94 "post": { 

95 "summary": "Create Hero", 

96 "operationId": "create_hero_heroes__post", 

97 "requestBody": { 

98 "content": { 

99 "application/json": { 

100 "schema": { 

101 "$ref": "#/components/schemas/HeroCreate" 

102 } 

103 } 

104 }, 

105 "required": True, 

106 }, 

107 "responses": { 

108 "200": { 

109 "description": "Successful Response", 

110 "content": { 

111 "application/json": { 

112 "schema": { 

113 "$ref": "#/components/schemas/HeroPublic" 

114 } 

115 } 

116 }, 

117 }, 

118 "422": { 

119 "description": "Validation Error", 

120 "content": { 

121 "application/json": { 

122 "schema": { 

123 "$ref": "#/components/schemas/HTTPValidationError" 

124 } 

125 } 

126 }, 

127 }, 

128 }, 

129 }, 

130 } 

131 }, 

132 "components": { 

133 "schemas": { 

134 "HTTPValidationError": { 

135 "title": "HTTPValidationError", 

136 "type": "object", 

137 "properties": { 

138 "detail": { 

139 "title": "Detail", 

140 "type": "array", 

141 "items": { 

142 "$ref": "#/components/schemas/ValidationError" 

143 }, 

144 } 

145 }, 

146 }, 

147 "HeroCreate": { 

148 "title": "HeroCreate", 

149 "required": ["name", "secret_name"], 

150 "type": "object", 

151 "properties": { 

152 "name": {"title": "Name", "type": "string"}, 

153 "secret_name": {"title": "Secret Name", "type": "string"}, 

154 "age": { 

155 "title": "Age", 

156 "anyOf": [{"type": "integer"}, {"type": "null"}], 

157 }, 

158 }, 

159 }, 

160 "HeroPublic": { 

161 "title": "HeroPublic", 

162 "required": ["id", "name", "secret_name"], 

163 "type": "object", 

164 "properties": { 

165 "id": {"title": "Id", "type": "integer"}, 

166 "name": {"title": "Name", "type": "string"}, 

167 "secret_name": {"title": "Secret Name", "type": "string"}, 

168 "age": { 

169 "title": "Age", 

170 "anyOf": [{"type": "integer"}, {"type": "null"}], 

171 }, 

172 }, 

173 }, 

174 "ValidationError": { 

175 "title": "ValidationError", 

176 "required": ["loc", "msg", "type"], 

177 "type": "object", 

178 "properties": IsOneOf( 

179 { 

180 "loc": { 

181 "title": "Location", 

182 "type": "array", 

183 "items": { 

184 "anyOf": [ 

185 {"type": "string"}, 

186 {"type": "integer"}, 

187 ] 

188 }, 

189 }, 

190 "msg": {"title": "Message", "type": "string"}, 

191 "type": {"title": "Error Type", "type": "string"}, 

192 }, 

193 { 

194 "loc": { 

195 "title": "Location", 

196 "type": "array", 

197 "items": { 

198 "anyOf": [ 

199 {"type": "string"}, 

200 {"type": "integer"}, 

201 ] 

202 }, 

203 }, 

204 "msg": {"title": "Message", "type": "string"}, 

205 "type": {"title": "Error Type", "type": "string"}, 

206 "ctx": {"title": "Context", "type": "object"}, 

207 "input": {"title": "Input"}, 

208 }, 

209 ), 

210 }, 

211 } 

212 }, 

213 } 

214 

215 # Test inherited indexes 

216 insp: Inspector = inspect(module.engine) 1abcdefghi

217 indexes = insp.get_indexes(str(module.Hero.__tablename__)) 1abcdefghi

218 assert { 1abcdefghi

219 index["name"]: (index["column_names"], index["unique"]) for index in indexes 

220 } == { 

221 "ix_hero_name": (["name"], False), 

222 "ix_hero_age": (["age"], False), 

223 }