Commit 631a27fe0dad5aca229f4186385488aad4662bee

Authored by biqiao
0 parents
Exists in master

first commit

Showing 51 changed files with 5323 additions and 0 deletions   Show diff stats
.idea/apiTest.iml
File was created 1 <?xml version="1.0" encoding="UTF-8"?>
2 <module type="PYTHON_MODULE" version="4">
3 <component name="NewModuleRootManager">
4 <content url="file://$MODULE_DIR$" />
5 <orderEntry type="inheritedJdk" />
6 <orderEntry type="sourceFolder" forTests="false" />
7 </component>
8 <component name="TestRunnerService">
9 <option name="PROJECT_TEST_RUNNER" value="Unittests" />
10 </component>
11 </module>
.idea/inspectionProfiles/Project_Default.xml
File was created 1 <component name="InspectionProjectProfileManager">
2 <profile version="1.0">
3 <option name="myName" value="Project Default" />
4 <inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
5 <option name="ignoredIdentifiers">
6 <list>
7 <option value="elecCard_setUp" />
8 </list>
9 </option>
10 </inspection_tool>
11 </profile>
12 </component>
File was created 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project version="4">
3 <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6.2 (/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6)" project-jdk-type="Python SDK" />
4 </project>
.idea/modules.xml
File was created 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project version="4">
3 <component name="ProjectModuleManager">
4 <modules>
5 <module fileurl="file://$PROJECT_DIR$/.idea/apiTest.iml" filepath="$PROJECT_DIR$/.idea/apiTest.iml" />
6 </modules>
7 </component>
8 </project>
File was created 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project version="4">
3 <component name="VcsDirectoryMappings">
4 <mapping directory="$PROJECT_DIR$" vcs="Git" />
5 </component>
6 </project>
.idea/workspace.xml
File was created 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project version="4">
3 <component name="ChangeListManager">
4 <list default="true" id="33187cb8-da74-4b13-8a55-31c4cae60a20" name="Default" comment="" />
5 <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
6 <option name="TRACKING_ENABLED" value="true" />
7 <option name="SHOW_DIALOG" value="false" />
8 <option name="HIGHLIGHT_CONFLICTS" value="true" />
9 <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
10 <option name="LAST_RESOLUTION" value="IGNORE" />
11 </component>
12 <component name="CoverageDataManager">
13 <SUITE FILE_PATH="coverage/apiTest$debugggggg.coverage" NAME="debugggggg Coverage Results" MODIFIED="1514886595342" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/test_cases" />
14 <SUITE FILE_PATH="coverage/apiTest$run_test.coverage" NAME="run_test Coverage Results" MODIFIED="1515151494257" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
15 </component>
16 <component name="DatabaseView">
17 <option name="SHOW_INTERMEDIATE" value="true" />
18 <option name="GROUP_SCHEMA" value="true" />
19 <option name="GROUP_CONTENTS" value="false" />
20 <option name="SORT_POSITIONED" value="false" />
21 <option name="SHOW_TABLE_DETAILS" value="true" />
22 <option name="SHOW_EMPTY_GROUPS" value="false" />
23 <option name="AUTO_SCROLL_FROM_SOURCE" value="false" />
24 <expand />
25 <select />
26 </component>
27 <component name="FileEditorManager">
28 <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
29 <file leaf-file-name="mysql_db.py" pinned="false" current-in-tab="false">
30 <entry file="file://$PROJECT_DIR$/data_fixture/mysql_db.py">
31 <provider selected="true" editor-type-id="text-editor">
32 <state relative-caret-position="34">
33 <caret line="2" column="0" lean-forward="true" selection-start-line="2" selection-start-column="0" selection-end-line="2" selection-end-column="0" />
34 <folding>
35 <marker date="1514616463000" expanded="true" signature="1672:1692" ph="select * fro... " />
36 <marker date="1514616463000" expanded="true" signature="1672:1694" ph="select * fro... missing_value" />
37 <marker date="1514616463000" expanded="true" signature="1672:1718" ph="select count... missing_value" />
38 <marker date="1514616463000" expanded="true" signature="1672:1719" ph="select count... missing_value" />
39 </folding>
40 </state>
41 </provider>
42 </entry>
43 </file>
44 <file leaf-file-name="app_record_statistic.py" pinned="false" current-in-tab="false">
45 <entry file="file://$PROJECT_DIR$/test_cases/app_record_statistic.py">
46 <provider selected="true" editor-type-id="text-editor">
47 <state relative-caret-position="761">
48 <caret line="170" column="45" lean-forward="false" selection-start-line="170" selection-start-column="45" selection-end-line="170" selection-end-column="45" />
49 <folding>
50 <element signature="e#47#62#0" expanded="true" />
51 </folding>
52 </state>
53 </provider>
54 </entry>
55 </file>
56 <file leaf-file-name="run_test.py" pinned="false" current-in-tab="true">
57 <entry file="file://$PROJECT_DIR$/run_test.py">
58 <provider selected="true" editor-type-id="text-editor">
59 <state relative-caret-position="289">
60 <caret line="17" column="0" lean-forward="true" selection-start-line="17" selection-start-column="0" selection-end-line="17" selection-end-column="0" />
61 <folding>
62 <element signature="e#47#62#0" expanded="true" />
63 </folding>
64 </state>
65 </provider>
66 </entry>
67 </file>
68 <file leaf-file-name="debugggggg.py" pinned="false" current-in-tab="false">
69 <entry file="file://$PROJECT_DIR$/test_cases/debugggggg.py">
70 <provider selected="true" editor-type-id="text-editor">
71 <state relative-caret-position="34">
72 <caret line="2" column="0" lean-forward="false" selection-start-line="2" selection-start-column="0" selection-end-line="2" selection-end-column="0" />
73 <folding />
74 </state>
75 </provider>
76 </entry>
77 </file>
78 <file leaf-file-name="subject_sync.py" pinned="false" current-in-tab="false">
79 <entry file="file://$PROJECT_DIR$/test_cases/subject_sync.py">
80 <provider selected="true" editor-type-id="text-editor">
81 <state relative-caret-position="85">
82 <caret line="5" column="66" lean-forward="true" selection-start-line="5" selection-start-column="66" selection-end-line="5" selection-end-column="66" />
83 <folding />
84 </state>
85 </provider>
86 </entry>
87 </file>
88 <file leaf-file-name="create_testdata.py" pinned="false" current-in-tab="false">
89 <entry file="file://$PROJECT_DIR$/data_fixture/create_testdata.py">
90 <provider selected="true" editor-type-id="text-editor">
91 <state relative-caret-position="310">
92 <caret line="356" column="79" lean-forward="false" selection-start-line="356" selection-start-column="67" selection-end-line="356" selection-end-column="79" />
93 <folding>
94 <element signature="e#47#83#0" expanded="true" />
95 <marker date="1515219431000" expanded="true" signature="1421:1488" ph="select * fro... ozing_customermachine" />
96 <marker date="1515219431000" expanded="true" signature="1421:1489" ph="select * fro... ozing_customermachine" />
97 <marker date="1515219431000" expanded="true" signature="1421:1491" ph="select * fro... ozing_customermachine" />
98 <marker date="1515219431000" expanded="true" signature="1421:1492" ph="select * fro... ozing_customermachine" />
99 <marker date="1515219431000" expanded="true" signature="1421:1518" ph="select * fro... ozing_customermachine" />
100 <marker date="1515219431000" expanded="true" signature="1549:1608" ph="SELECT * FRO... ozing_machine" />
101 <marker date="1515219431000" expanded="true" signature="1549:1609" ph="SELECT * FRO... ozing_machine" />
102 <marker date="1515219431000" expanded="true" signature="1549:1612" ph="SELECT * FRO... ozing_machine" />
103 <marker date="1515219431000" expanded="true" signature="1549:1613" ph="SELECT * FRO... ozing_machine" />
104 <marker date="1515219431000" expanded="true" signature="1549:1639" ph="SELECT * FRO... ozing_machine" />
105 <marker date="1515219431000" expanded="true" signature="1752:2214" ph="insert into acornuser.ozing_customermachine... " />
106 <marker date="1515219431000" expanded="true" signature="2928:2997" ph="SELECT * FRO... ozing_samplemachine" />
107 <marker date="1515219431000" expanded="true" signature="3049:3113" ph="SELECT * FRO... ozing_machine" />
108 <marker date="1515219431000" expanded="true" signature="4735:4806" ph="select * fro... ozing_customermachine" />
109 <marker date="1515219431000" expanded="true" signature="5151:5215" ph="SELECT * FRO... ozing_machine" />
110 <marker date="1515219431000" expanded="true" signature="5276:5356" ph="SELECT * FRO... ozing_machine" />
111 <marker date="1515219431000" expanded="true" signature="6222:6293" ph="select * fro... ozing_customermachine" />
112 <marker date="1515219431000" expanded="true" signature="6578:6641" ph="select * fro... ozing_machine" />
113 <marker date="1515219431000" expanded="true" signature="7715:7780" ph="update acorn... " />
114 <marker date="1515219431000" expanded="true" signature="7715:7804" ph="update acorn... " />
115 <marker date="1515219431000" expanded="true" signature="7928:8009" ph="select * fro... child_user" />
116 <marker date="1515219431000" expanded="true" signature="8075:8156" ph="select * fro... child_user" />
117 <marker date="1515219431000" expanded="true" signature="8075:8203" ph="select * fro... child_user" />
118 <marker date="1515219431000" expanded="true" signature="8075:8205" ph="select * fro... child_user" />
119 <marker date="1515219431000" expanded="true" signature="9093:9178" ph="select * fro... acorn_user_status" />
120 <marker date="1515219431000" expanded="true" signature="9320:9420" ph="select * fro... acorn_user_status" />
121 <marker date="1515219431000" expanded="true" signature="10158:10258" ph="select * fro... acorn_user_status" />
122 <marker date="1515219431000" expanded="true" signature="11302:11360" ph="select * fro... acorn_user_extra" />
123 <marker date="1515219431000" expanded="true" signature="11397:11483" ph="select * fro... acorn_user_extra" />
124 <marker date="1515219431000" expanded="true" signature="11914:11983" ph="select * fro... subAccount_user_extra" />
125 <marker date="1515219431000" expanded="true" signature="11914:11984" ph="select * fro... subAccount_user_extra" />
126 <marker date="1515219431000" expanded="true" signature="11914:11988" ph="select * fro... subAccount_user_extra" />
127 <marker date="1515219431000" expanded="true" signature="12023:12092" ph="select * fro... subAccount_user_extra" />
128 <marker date="1515219431000" expanded="true" signature="12023:12122" ph="select * fro... subAccount_user_extra" />
129 <marker date="1515219431000" expanded="true" signature="12023:12138" ph="select * fro... subAccount_user_extra" />
130 <marker date="1515219431000" expanded="true" signature="13348:13448" ph="select * fro... ozing_student" />
131 <marker date="1515219431000" expanded="true" signature="13550:13636" ph="update acorn... " />
132 <marker date="1515219431000" expanded="true" signature="13550:13638" ph="update acorn... " />
133 <marker date="1515219431000" expanded="true" signature="13726:13834" ph="select * fro... ozing_student" />
134 <marker date="1515219431000" expanded="true" signature="15966:16006" ph="select max(i... acorn_user" />
135 <marker date="1515219431000" expanded="true" signature="15966:16008" ph="select max(i... acorn_user" />
136 <marker date="1515219431000" expanded="true" signature="16721:16796" ph="select passw... parents_space_pass" />
137 <marker date="1515219431000" expanded="true" signature="17752:17804" ph="update analy... " />
138 <marker date="1515219431000" expanded="true" signature="17752:17821" ph="update analy... " />
139 <marker date="1515219431000" expanded="true" signature="17752:17849" ph="update analy... " />
140 <marker date="1515219431000" expanded="true" signature="17752:17850" ph="update analy... " />
141 </folding>
142 </state>
143 </provider>
144 </entry>
145 </file>
146 <file leaf-file-name="config_data.py" pinned="false" current-in-tab="false">
147 <entry file="file://$PROJECT_DIR$/data_fixture/config_data.py">
148 <provider selected="true" editor-type-id="text-editor">
149 <state relative-caret-position="114">
150 <caret line="12" column="14" lean-forward="false" selection-start-line="12" selection-start-column="14" selection-end-line="12" selection-end-column="14" />
151 <folding />
152 </state>
153 </provider>
154 </entry>
155 </file>
156 </leaf>
157 </component>
158 <component name="FileTemplateManagerImpl">
159 <option name="RECENT_TEMPLATES">
160 <list>
161 <option value="Python Script" />
162 </list>
163 </option>
164 </component>
165 <component name="FindInProjectRecents">
166 <findStrings>
167 <find>_generate_report</find>
168 <find>Data</find>
169 <find>test_unbindCard_success</find>
170 <find>login</find>
171 <find>DEVICE_NUMBER_EDIT_PHONE</find>
172 <find>pre_SetUpElecCard</find>
173 <find>authCode</find>
174 <find>subaccountswitch001</find>
175 <find>pre_AddSubAccount</find>
176 <find>parent_id</find>
177 <find>USER_ID</find>
178 <find>USER_PHONE_EDIT</find>
179 <find>RegisterExtrainfoCheck</find>
180 <find>png</find>
181 <find>checkSignatureExists</find>
182 <find>SUB_ACC_GET_ID_1</find>
183 <find>SUB_ACC_GET_ID_</find>
184 <find>SUB_ACC_DEL_ID_2</find>
185 <find>SUB_ACC_SWITCH_ID_1</find>
186 <find>SUB_ACC</find>
187 <find>pre_subAccount</find>
188 <find>pre_elecCard</find>
189 <find>保卡</find>
190 <find>'time_spend'</find>
191 <find>select_</find>
192 <find>Data.DEVICE_NUMBER_CUS_BIND</find>
193 <find>SUB_ACC_</find>
194 <find>test_getAppRecordOneday_success</find>
195 <find>get_parentSpace_password</find>
196 <find>print</find>
197 </findStrings>
198 <replaceStrings>
199 <replace>app_pid</replace>
200 <replace>'app_pid'</replace>
201 <replace>'time_spent'</replace>
202 <replace>user_id</replace>
203 <replace>device_number</replace>
204 <replace>PARENT_ID</replace>
205 </replaceStrings>
206 <dirStrings>
207 <dir>$PROJECT_DIR$</dir>
208 </dirStrings>
209 </component>
210 <component name="IdeDocumentHistory">
211 <option name="CHANGED_PATHS">
212 <list>
213 <option value="$PROJECT_DIR$/tests/elecCard.py" />
214 <option value="$PROJECT_DIR$/db_fixture/mysql_db.py" />
215 <option value="$PROJECT_DIR$/tests/configParse'.py" />
216 <option value="$PROJECT_DIR$/tests/configParse.py" />
217 <option value="$PROJECT_DIR$/tests/personalCenter/elecCardFlow_test.py" />
218 <option value="$PROJECT_DIR$/tests/personalCenter/elecCard_setUp.py" />
219 <option value="$PROJECT_DIR$/tests/personalCenter/elecCard/elecCard_setUp.py" />
220 <option value="$PROJECT_DIR$/tests/personalCenter/elecCard/elecCard_check.py" />
221 <option value="$PROJECT_DIR$/tests/test_suites/test_elecCard.py" />
222 <option value="$PROJECT_DIR$/tests/test_cases/__init__.py" />
223 <option value="$PROJECT_DIR$/test_suites/test_elecCard.py" />
224 <option value="$PROJECT_DIR$/data_fixture/UthCode.py" />
225 <option value="/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/HtmlTestRunner/runner.py" />
226 <option value="$PROJECT_DIR$/config.ini" />
227 <option value="$PROJECT_DIR$/HTMLTestRunner.py" />
228 <option value="$PROJECT_DIR$/test_cases/elecCard_check.py" />
229 <option value="$PROJECT_DIR$/data_fixture/authCode.py" />
230 <option value="$PROJECT_DIR$/test_cases/elecCard_setUp.py" />
231 <option value="$PROJECT_DIR$/data_fixture/test_verify.py" />
232 <option value="$PROJECT_DIR$/test_cases/region_grade_school.py" />
233 <option value="$PROJECT_DIR$/test_cases/eleccard_setUp.py" />
234 <option value="$PROJECT_DIR$/test_cases/press.py" />
235 <option value="$PROJECT_DIR$/test_cases/sub_account.py" />
236 <option value="$PROJECT_DIR$/test_cases/register.py" />
237 <option value="$PROJECT_DIR$/test_cases/personal_info.py" />
238 <option value="$PROJECT_DIR$/data_fixture/config_data.py" />
239 <option value="$PROJECT_DIR$/data_fixture/mysql_db.py" />
240 <option value="$PROJECT_DIR$/test_cases/parent_space.py" />
241 <option value="$PROJECT_DIR$/test_cases/xueketongbu.py" />
242 <option value="$PROJECT_DIR$/test_cases/app_record_statistic.py" />
243 <option value="$PROJECT_DIR$/data_fixture/create_testdata.py" />
244 <option value="$PROJECT_DIR$/test_cases/debugggggg.py" />
245 <option value="$PROJECT_DIR$/run_test.py" />
246 <option value="$PROJECT_DIR$/test_cases/__init__.py" />
247 <option value="$PROJECT_DIR$/data_fixture/__init__.py" />
248 <option value="$PROJECT_DIR$/test_cases/subject_sync.py" />
249 </list>
250 </option>
251 </component>
252 <component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
253 <component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
254 <component name="JsGulpfileManager">
255 <detection-done>true</detection-done>
256 <sorting>DEFINITION_ORDER</sorting>
257 </component>
258 <component name="ProjectFrameBounds" extendedState="6">
259 <option name="x" value="23" />
260 <option name="y" value="85" />
261 <option name="width" value="1920" />
262 <option name="height" value="977" />
263 </component>
264 <component name="ProjectView">
265 <navigator currentView="ProjectPane" proportions="" version="1">
266 <flattenPackages />
267 <showMembers />
268 <showModules />
269 <showLibraryContents />
270 <hideEmptyPackages />
271 <abbreviatePackageNames />
272 <autoscrollToSource />
273 <autoscrollFromSource />
274 <sortByType />
275 <manualOrder />
276 <foldersAlwaysOnTop value="true" />
277 </navigator>
278 <panes>
279 <pane id="Scope" />
280 <pane id="ProjectPane">
281 <subPane>
282 <expand>
283 <path>
284 <item name="apiTest" type="b2602c69:ProjectViewProjectNode" />
285 <item name="apiTest" type="462c0819:PsiDirectoryNode" />
286 </path>
287 <path>
288 <item name="apiTest" type="b2602c69:ProjectViewProjectNode" />
289 <item name="apiTest" type="462c0819:PsiDirectoryNode" />
290 <item name="data_fixture" type="462c0819:PsiDirectoryNode" />
291 </path>
292 <path>
293 <item name="apiTest" type="b2602c69:ProjectViewProjectNode" />
294 <item name="apiTest" type="462c0819:PsiDirectoryNode" />
295 <item name="report" type="462c0819:PsiDirectoryNode" />
296 </path>
297 <path>
298 <item name="apiTest" type="b2602c69:ProjectViewProjectNode" />
299 <item name="apiTest" type="462c0819:PsiDirectoryNode" />
300 <item name="test_cases" type="462c0819:PsiDirectoryNode" />
301 </path>
302 <path>
303 <item name="apiTest" type="b2602c69:ProjectViewProjectNode" />
304 <item name="apiTest" type="462c0819:PsiDirectoryNode" />
305 <item name="test_suites" type="462c0819:PsiDirectoryNode" />
306 </path>
307 </expand>
308 <select />
309 </subPane>
310 </pane>
311 <pane id="Scratches" />
312 </panes>
313 </component>
314 <component name="PropertiesComponent">
315 <property name="WebServerToolWindowFactoryState" value="false" />
316 <property name="settings.editor.selected.configurable" value="editor.preferences.folding" />
317 </component>
318 <component name="RecentsManager">
319 <key name="MoveFile.RECENT_KEYS">
320 <recent name="$PROJECT_DIR$/test_cases" />
321 <recent name="$PROJECT_DIR$" />
322 <recent name="$PROJECT_DIR$/tests" />
323 <recent name="$PROJECT_DIR$/tests/test_cases" />
324 <recent name="$PROJECT_DIR$/tests/test_cases/personalCenter" />
325 </key>
326 <key name="CopyFile.RECENT_KEYS">
327 <recent name="$PROJECT_DIR$/test_cases" />
328 <recent name="$PROJECT_DIR$" />
329 </key>
330 </component>
331 <component name="RunDashboard">
332 <option name="ruleStates">
333 <list>
334 <RuleState>
335 <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
336 </RuleState>
337 <RuleState>
338 <option name="name" value="StatusDashboardGroupingRule" />
339 </RuleState>
340 </list>
341 </option>
342 </component>
343 <component name="RunManager" selected="Python.run_test">
344 <configuration name="debugggggg" type="PythonConfigurationType" factoryName="Python" temporary="true">
345 <option name="INTERPRETER_OPTIONS" value="" />
346 <option name="PARENT_ENVS" value="true" />
347 <envs>
348 <env name="PYTHONUNBUFFERED" value="1" />
349 </envs>
350 <option name="SDK_HOME" value="" />
351 <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/test_cases" />
352 <option name="IS_MODULE_SDK" value="true" />
353 <option name="ADD_CONTENT_ROOTS" value="true" />
354 <option name="ADD_SOURCE_ROOTS" value="true" />
355 <module name="apiTest" />
356 <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
357 <option name="SCRIPT_NAME" value="$PROJECT_DIR$/test_cases/debugggggg.py" />
358 <option name="PARAMETERS" value="" />
359 <option name="SHOW_COMMAND_LINE" value="false" />
360 <option name="EMULATE_TERMINAL" value="false" />
361 </configuration>
362 <configuration name="run_test" type="PythonConfigurationType" factoryName="Python" temporary="true">
363 <option name="INTERPRETER_OPTIONS" value="" />
364 <option name="PARENT_ENVS" value="true" />
365 <envs>
366 <env name="PYTHONUNBUFFERED" value="1" />
367 </envs>
368 <option name="SDK_HOME" value="" />
369 <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
370 <option name="IS_MODULE_SDK" value="true" />
371 <option name="ADD_CONTENT_ROOTS" value="true" />
372 <option name="ADD_SOURCE_ROOTS" value="true" />
373 <module name="apiTest" />
374 <EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
375 <option name="SCRIPT_NAME" value="$PROJECT_DIR$/run_test.py" />
376 <option name="PARAMETERS" value="" />
377 <option name="SHOW_COMMAND_LINE" value="false" />
378 <option name="EMULATE_TERMINAL" value="false" />
379 </configuration>
380 <list size="2">
381 <item index="0" class="java.lang.String" itemvalue="Python.run_test" />
382 <item index="1" class="java.lang.String" itemvalue="Python.debugggggg" />
383 </list>
384 <recent_temporary>
385 <list size="2">
386 <item index="0" class="java.lang.String" itemvalue="Python.run_test" />
387 <item index="1" class="java.lang.String" itemvalue="Python.debugggggg" />
388 </list>
389 </recent_temporary>
390 </component>
391 <component name="ShelveChangesManager" show_recycled="false">
392 <option name="remove_strategy" value="false" />
393 </component>
394 <component name="TaskManager">
395 <task active="true" id="Default" summary="Default task">
396 <changelist id="33187cb8-da74-4b13-8a55-31c4cae60a20" name="Default" comment="" />
397 <created>1512799492607</created>
398 <option name="number" value="Default" />
399 <option name="presentableId" value="Default" />
400 <updated>1512799492607</updated>
401 </task>
402 <servers />
403 </component>
404 <component name="TodoView">
405 <todo-panel id="selected-file">
406 <is-autoscroll-to-source value="true" />
407 </todo-panel>
408 <todo-panel id="all">
409 <are-packages-shown value="true" />
410 <is-autoscroll-to-source value="true" />
411 </todo-panel>
412 </component>
413 <component name="ToolWindowManager">
414 <frame x="-9" y="23" width="1920" height="977" extended-state="6" />
415 <editor active="true" />
416 <layout>
417 <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32993197" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
418 <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
419 <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
420 <window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.24829932" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
421 <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2857143" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
422 <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32993197" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
423 <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.17891374" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
424 <window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32960597" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
425 <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
426 <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
427 <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
428 <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4580499" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
429 <window_info id="Data View" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.2284345" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
430 <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
431 <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
432 <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
433 <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
434 <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
435 <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
436 </layout>
437 <layout-to-restore>
438 <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32993197" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
439 <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
440 <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
441 <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
442 <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
443 <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
444 <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
445 <window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32993197" sideWeight="0.5" order="9" side_tool="false" content_ui="tabs" />
446 <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.22108844" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
447 <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32993197" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
448 <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.17571884" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
449 <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
450 <window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
451 <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
452 <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
453 <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
454 <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
455 <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.34807256" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
456 <window_info id="Data View" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
457 </layout-to-restore>
458 </component>
459 <component name="TypeScriptGeneratedFilesManager">
460 <option name="version" value="1" />
461 </component>
462 <component name="VcsContentAnnotationSettings">
463 <option name="myLimit" value="2678400000" />
464 </component>
465 <component name="XDebuggerManager">
466 <breakpoint-manager>
467 <breakpoints>
468 <line-breakpoint enabled="true" suspend="THREAD" type="python-line">
469 <url>file://$PROJECT_DIR$/test_cases/sub_account.py</url>
470 <line>56</line>
471 <option name="timeStamp" value="82" />
472 </line-breakpoint>
473 <line-breakpoint enabled="true" suspend="THREAD" type="python-line">
474 <url>file://$PROJECT_DIR$/test_cases/register.py</url>
475 <line>19</line>
476 <option name="timeStamp" value="102" />
477 </line-breakpoint>
478 <line-breakpoint enabled="true" suspend="THREAD" type="python-line">
479 <url>file://$PROJECT_DIR$/test_cases/personal_info.py</url>
480 <line>253</line>
481 <option name="timeStamp" value="113" />
482 </line-breakpoint>
483 <line-breakpoint enabled="true" suspend="THREAD" type="python-line">
484 <url>file://$PROJECT_DIR$/test_cases/debugggggg.py</url>
485 <line>18</line>
486 <option name="timeStamp" value="140" />
487 </line-breakpoint>
488 <line-breakpoint enabled="true" suspend="THREAD" type="python-line">
489 <url>file://$PROJECT_DIR$/test_cases/app_record_statistic.py</url>
490 <line>181</line>
491 <option name="timeStamp" value="188" />
492 </line-breakpoint>
493 </breakpoints>
494 <breakpoints-dialog>
495 <breakpoints-dialog />
496 </breakpoints-dialog>
497 <option name="time" value="189" />
498 </breakpoint-manager>
499 <watches-manager />
500 </component>
501 <component name="editorHistoryManager">
502 <entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/suite.py">
503 <provider selected="true" editor-type-id="text-editor">
504 <state relative-caret-position="1360">
505 <caret line="83" column="0" lean-forward="false" selection-start-line="83" selection-start-column="0" selection-end-line="83" selection-end-column="0" />
506 <folding />
507 </state>
508 </provider>
509 </entry>
510 <entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/codecs.py">
511 <provider selected="true" editor-type-id="text-editor">
512 <state relative-caret-position="5627">
513 <caret line="331" column="0" lean-forward="false" selection-start-line="331" selection-start-column="0" selection-end-line="331" selection-end-column="0" />
514 </state>
515 </provider>
516 </entry>
517 <entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/HtmlTestRunner/runner.py" />
518 <entry file="file://$PROJECT_DIR$/config.ini" />
519 <entry file="file://$PROJECT_DIR$/data_fixture/mysql_db.py">
520 <provider selected="true" editor-type-id="text-editor">
521 <state relative-caret-position="0">
522 <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="18" selection-end-column="0" />
523 <folding>
524 <marker date="1514616463000" expanded="true" signature="1672:1692" ph="select * fro... " />
525 <marker date="1514616463000" expanded="true" signature="1672:1694" ph="select * fro... missing_value" />
526 <marker date="1514616463000" expanded="true" signature="1672:1718" ph="select count... missing_value" />
527 <marker date="1514616463000" expanded="true" signature="1672:1719" ph="select count... missing_value" />
528 </folding>
529 </state>
530 </provider>
531 </entry>
532 <entry file="file://$PROJECT_DIR$/configParse.py">
533 <provider selected="true" editor-type-id="text-editor">
534 <state relative-caret-position="238">
535 <caret line="16" column="45" lean-forward="false" selection-start-line="16" selection-start-column="45" selection-end-line="16" selection-end-column="45" />
536 </state>
537 </provider>
538 </entry>
539 <entry file="file://$PROJECT_DIR$/test_cases/eleccard_setUp.py">
540 <provider selected="true" editor-type-id="text-editor">
541 <state relative-caret-position="748">
542 <caret line="47" column="0" lean-forward="false" selection-start-line="47" selection-start-column="0" selection-end-line="47" selection-end-column="0" />
543 <folding />
544 </state>
545 </provider>
546 </entry>
547 <entry file="file://$PROJECT_DIR$/test_cases/eleccard_check.py">
548 <provider selected="true" editor-type-id="text-editor">
549 <state relative-caret-position="816">
550 <caret line="51" column="23" lean-forward="false" selection-start-line="51" selection-start-column="23" selection-end-line="51" selection-end-column="23" />
551 <folding />
552 </state>
553 </provider>
554 </entry>
555 <entry file="file://$PROJECT_DIR$/config.ini" />
556 <entry file="file://$PROJECT_DIR$/data_fixture/mysql_db.py">
557 <provider selected="true" editor-type-id="text-editor">
558 <state relative-caret-position="0">
559 <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="18" selection-end-column="0" />
560 <folding>
561 <marker date="1514616463000" expanded="true" signature="1672:1692" ph="select * fro... " />
562 <marker date="1514616463000" expanded="true" signature="1672:1694" ph="select * fro... missing_value" />
563 <marker date="1514616463000" expanded="true" signature="1672:1718" ph="select count... missing_value" />
564 <marker date="1514616463000" expanded="true" signature="1672:1719" ph="select count... missing_value" />
565 </folding>
566 </state>
567 </provider>
568 </entry>
569 <entry file="file://$PROJECT_DIR$/configParse.py">
570 <provider selected="true" editor-type-id="text-editor">
571 <state relative-caret-position="272">
572 <caret line="16" column="45" lean-forward="true" selection-start-line="16" selection-start-column="45" selection-end-line="16" selection-end-column="45" />
573 </state>
574 </provider>
575 </entry>
576 <entry file="file://$PROJECT_DIR$/test_cases/eleccard_setUp.py">
577 <provider selected="true" editor-type-id="text-editor">
578 <state relative-caret-position="799">
579 <caret line="47" column="0" lean-forward="true" selection-start-line="47" selection-start-column="0" selection-end-line="47" selection-end-column="0" />
580 <folding />
581 </state>
582 </provider>
583 </entry>
584 <entry file="file://$PROJECT_DIR$/test_cases/eleccard_check.py">
585 <provider selected="true" editor-type-id="text-editor">
586 <state relative-caret-position="867">
587 <caret line="51" column="23" lean-forward="true" selection-start-line="51" selection-start-column="23" selection-end-line="51" selection-end-column="23" />
588 <folding />
589 </state>
590 </provider>
591 </entry>
592 <entry file="file://$PROJECT_DIR$/configParse.py">
593 <provider selected="true" editor-type-id="text-editor">
594 <state relative-caret-position="0">
595 <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
596 </state>
597 </provider>
598 </entry>
599 <entry file="file://$PROJECT_DIR$/tests/test_cases/__init__.py" />
600 <entry file="file://$PROJECT_DIR$/configParse.py">
601 <provider selected="true" editor-type-id="text-editor">
602 <state relative-caret-position="272">
603 <caret line="16" column="45" lean-forward="false" selection-start-line="16" selection-start-column="45" selection-end-line="16" selection-end-column="45" />
604 </state>
605 </provider>
606 </entry>
607 <entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/codecs.py">
608 <provider selected="true" editor-type-id="text-editor">
609 <state relative-caret-position="5627">
610 <caret line="331" column="0" lean-forward="false" selection-start-line="331" selection-start-column="0" selection-end-line="331" selection-end-column="0" />
611 </state>
612 </provider>
613 </entry>
614 <entry file="file://$PROJECT_DIR$/reports/report/Test_region_grade_school.Getrades_2017-12-13_11-29-12.html" />
615 <entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/HtmlTestRunner/runner.py" />
616 <entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/encodings/ascii.py">
617 <provider selected="true" editor-type-id="text-editor">
618 <state relative-caret-position="372">
619 <caret line="25" column="0" lean-forward="false" selection-start-line="25" selection-start-column="0" selection-end-line="25" selection-end-column="0" />
620 </state>
621 </provider>
622 </entry>
623 <entry file="file://$PROJECT_DIR$/config.ini" />
624 <entry file="file://$PROJECT_DIR$/HTMLTestRunner.py">
625 <provider selected="true" editor-type-id="text-editor">
626 <state relative-caret-position="313">
627 <caret line="188" column="6" lean-forward="true" selection-start-line="185" selection-start-column="4" selection-end-line="296" selection-end-column="3" />
628 <folding>
629 <element signature="e#8852#10678#0" expanded="false" />
630 </folding>
631 </state>
632 </provider>
633 </entry>
634 <entry file="file://$PROJECT_DIR$/HTMLTestRunner_bak.py">
635 <provider selected="true" editor-type-id="text-editor">
636 <state relative-caret-position="0">
637 <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
638 </state>
639 </provider>
640 </entry>
641 <entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/suite.py">
642 <provider selected="true" editor-type-id="text-editor">
643 <state relative-caret-position="149">
644 <caret line="83" column="0" lean-forward="false" selection-start-line="83" selection-start-column="0" selection-end-line="83" selection-end-column="0" />
645 <folding />
646 </state>
647 </provider>
648 </entry>
649 <entry file="file://$PROJECT_DIR$/test_suites/test_elecCard.py">
650 <provider selected="true" editor-type-id="text-editor">
651 <state relative-caret-position="0">
652 <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="1" selection-end-column="23" />
653 </state>
654 </provider>
655 </entry>
656 <entry file="file://$PROJECT_DIR$/data_fixture/authCode.py" />
657 <entry file="file://$PROJECT_DIR$/test_cases/eleccard_check.py">
658 <provider selected="true" editor-type-id="text-editor">
659 <state relative-caret-position="136">
660 <caret line="8" column="44" lean-forward="true" selection-start-line="8" selection-start-column="44" selection-end-line="8" selection-end-column="44" />
661 <folding />
662 </state>
663 </provider>
664 </entry>
665 <entry file="file://$PROJECT_DIR$/data_fixture/test_verify.py">
666 <provider selected="true" editor-type-id="text-editor">
667 <state relative-caret-position="187">
668 <caret line="11" column="0" lean-forward="true" selection-start-line="11" selection-start-column="0" selection-end-line="11" selection-end-column="0" />
669 </state>
670 </provider>
671 </entry>
672 <entry file="file://$PROJECT_DIR$/test_cases/region_grade_school.py">
673 <provider selected="true" editor-type-id="text-editor">
674 <state relative-caret-position="340">
675 <caret line="20" column="81" lean-forward="true" selection-start-line="8" selection-start-column="0" selection-end-line="20" selection-end-column="81" />
676 <folding>
677 <element signature="e#47#62#0" expanded="false" />
678 </folding>
679 </state>
680 </provider>
681 </entry>
682 <entry file="file://$PROJECT_DIR$/test_cases/252ED989-0B16-4AB7-81C1-974ABCF6CA11.png" />
683 <entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pymysql/cursors.py">
684 <provider selected="true" editor-type-id="text-editor">
685 <state relative-caret-position="240">
686 <caret line="166" column="0" lean-forward="false" selection-start-line="166" selection-start-column="0" selection-end-line="166" selection-end-column="0" />
687 <folding />
688 </state>
689 </provider>
690 </entry>
691 <entry file="file://$PROJECT_DIR$/test_cases/eleccard_setUp.py">
692 <provider selected="true" editor-type-id="text-editor">
693 <state relative-caret-position="209">
694 <caret line="102" column="26" lean-forward="true" selection-start-line="102" selection-start-column="26" selection-end-line="102" selection-end-column="26" />
695 <folding />
696 </state>
697 </provider>
698 </entry>
699 <entry file="file://$APPLICATION_HOME_DIR$/helpers/pydev/pydevd.py">
700 <provider selected="true" editor-type-id="text-editor">
701 <state relative-caret-position="169">
702 <caret line="1595" column="0" lean-forward="false" selection-start-line="1595" selection-start-column="0" selection-end-line="1595" selection-end-column="0" />
703 <folding />
704 </state>
705 </provider>
706 </entry>
707 <entry file="file://$PROJECT_DIR$/test_cases/press.py">
708 <provider selected="true" editor-type-id="text-editor">
709 <state relative-caret-position="0">
710 <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="11" selection-end-column="0" />
711 <folding />
712 </state>
713 </provider>
714 </entry>
715 <entry file="file://$PROJECT_DIR$/test_cases/register.py">
716 <provider selected="true" editor-type-id="text-editor">
717 <state relative-caret-position="17">
718 <caret line="205" column="22" lean-forward="false" selection-start-line="205" selection-start-column="22" selection-end-line="205" selection-end-column="22" />
719 <folding>
720 <element signature="e#47#62#0" expanded="true" />
721 </folding>
722 </state>
723 </provider>
724 </entry>
725 <entry file="file://$PROJECT_DIR$/HTMLTestRunner.py">
726 <provider selected="true" editor-type-id="text-editor">
727 <state relative-caret-position="165">
728 <caret line="643" column="0" lean-forward="false" selection-start-line="643" selection-start-column="0" selection-end-line="643" selection-end-column="0" />
729 <folding>
730 <element signature="e#8852#10678#0" expanded="false" />
731 </folding>
732 </state>
733 </provider>
734 </entry>
735 <entry file="file://$PROJECT_DIR$/test_cases/personal_info.py">
736 <provider selected="true" editor-type-id="text-editor">
737 <state relative-caret-position="415">
738 <caret line="251" column="26" lean-forward="false" selection-start-line="251" selection-start-column="26" selection-end-line="251" selection-end-column="26" />
739 <folding>
740 <element signature="e#47#62#0" expanded="true" />
741 </folding>
742 </state>
743 </provider>
744 </entry>
745 <entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pymysql/connections.py">
746 <provider selected="true" editor-type-id="text-editor">
747 <state relative-caret-position="176">
748 <caret line="1334" column="0" lean-forward="false" selection-start-line="1334" selection-start-column="0" selection-end-line="1334" selection-end-column="0" />
749 <folding />
750 </state>
751 </provider>
752 </entry>
753 <entry file="file://$PROJECT_DIR$/test_cases/parent_space.py">
754 <provider selected="true" editor-type-id="text-editor">
755 <state relative-caret-position="713">
756 <caret line="105" column="0" lean-forward="false" selection-start-line="105" selection-start-column="0" selection-end-line="105" selection-end-column="0" />
757 <folding>
758 <element signature="e#47#62#0" expanded="true" />
759 <marker date="1514955274000" expanded="true" signature="2800:2884" ph="SELECT custo... ozing_customermachine" />
760 </folding>
761 </state>
762 </provider>
763 </entry>
764 <entry file="file://$PROJECT_DIR$/test_cases/sub_account.py">
765 <provider selected="true" editor-type-id="text-editor">
766 <state relative-caret-position="423">
767 <caret line="51" column="41" lean-forward="true" selection-start-line="51" selection-start-column="41" selection-end-line="51" selection-end-column="41" />
768 <folding>
769 <element signature="e#47#62#0" expanded="true" />
770 </folding>
771 </state>
772 </provider>
773 </entry>
774 <entry file="file://$PROJECT_DIR$/report/test_report.html">
775 <provider selected="true" editor-type-id="text-editor">
776 <state relative-caret-position="0">
777 <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
778 <folding />
779 </state>
780 </provider>
781 </entry>
782 <entry file="file:///Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/case.py">
783 <provider selected="true" editor-type-id="text-editor">
784 <state relative-caret-position="359">
785 <caret line="600" column="0" lean-forward="false" selection-start-line="600" selection-start-column="0" selection-end-line="600" selection-end-column="0" />
786 <folding />
787 </state>
788 </provider>
789 </entry>
790 <entry file="file://$PROJECT_DIR$/data_fixture/config_data.py">
791 <provider selected="true" editor-type-id="text-editor">
792 <state relative-caret-position="114">
793 <caret line="12" column="14" lean-forward="false" selection-start-line="12" selection-start-column="14" selection-end-line="12" selection-end-column="14" />
794 <folding />
795 </state>
796 </provider>
797 </entry>
798 <entry file="file://$PROJECT_DIR$/data_fixture/create_testdata.py">
799 <provider selected="true" editor-type-id="text-editor">
800 <state relative-caret-position="310">
801 <caret line="356" column="79" lean-forward="false" selection-start-line="356" selection-start-column="67" selection-end-line="356" selection-end-column="79" />
802 <folding>
803 <element signature="e#47#83#0" expanded="true" />
804 <marker date="1515219431000" expanded="true" signature="1421:1488" ph="select * fro... ozing_customermachine" />
805 <marker date="1515219431000" expanded="true" signature="1421:1489" ph="select * fro... ozing_customermachine" />
806 <marker date="1515219431000" expanded="true" signature="1421:1491" ph="select * fro... ozing_customermachine" />
807 <marker date="1515219431000" expanded="true" signature="1421:1492" ph="select * fro... ozing_customermachine" />
808 <marker date="1515219431000" expanded="true" signature="1421:1518" ph="select * fro... ozing_customermachine" />
809 <marker date="1515219431000" expanded="true" signature="1549:1608" ph="SELECT * FRO... ozing_machine" />
810 <marker date="1515219431000" expanded="true" signature="1549:1609" ph="SELECT * FRO... ozing_machine" />
811 <marker date="1515219431000" expanded="true" signature="1549:1612" ph="SELECT * FRO... ozing_machine" />
812 <marker date="1515219431000" expanded="true" signature="1549:1613" ph="SELECT * FRO... ozing_machine" />
813 <marker date="1515219431000" expanded="true" signature="1549:1639" ph="SELECT * FRO... ozing_machine" />
814 <marker date="1515219431000" expanded="true" signature="1752:2214" ph="insert into acornuser.ozing_customermachine... " />
815 <marker date="1515219431000" expanded="true" signature="2928:2997" ph="SELECT * FRO... ozing_samplemachine" />
816 <marker date="1515219431000" expanded="true" signature="3049:3113" ph="SELECT * FRO... ozing_machine" />
817 <marker date="1515219431000" expanded="true" signature="4735:4806" ph="select * fro... ozing_customermachine" />
818 <marker date="1515219431000" expanded="true" signature="5151:5215" ph="SELECT * FRO... ozing_machine" />
819 <marker date="1515219431000" expanded="true" signature="5276:5356" ph="SELECT * FRO... ozing_machine" />
820 <marker date="1515219431000" expanded="true" signature="6222:6293" ph="select * fro... ozing_customermachine" />
821 <marker date="1515219431000" expanded="true" signature="6578:6641" ph="select * fro... ozing_machine" />
822 <marker date="1515219431000" expanded="true" signature="7715:7780" ph="update acorn... " />
823 <marker date="1515219431000" expanded="true" signature="7715:7804" ph="update acorn... " />
824 <marker date="1515219431000" expanded="true" signature="7928:8009" ph="select * fro... child_user" />
825 <marker date="1515219431000" expanded="true" signature="8075:8156" ph="select * fro... child_user" />
826 <marker date="1515219431000" expanded="true" signature="8075:8203" ph="select * fro... child_user" />
827 <marker date="1515219431000" expanded="true" signature="8075:8205" ph="select * fro... child_user" />
828 <marker date="1515219431000" expanded="true" signature="9093:9178" ph="select * fro... acorn_user_status" />
829 <marker date="1515219431000" expanded="true" signature="9320:9420" ph="select * fro... acorn_user_status" />
830 <marker date="1515219431000" expanded="true" signature="10158:10258" ph="select * fro... acorn_user_status" />
831 <marker date="1515219431000" expanded="true" signature="11302:11360" ph="select * fro... acorn_user_extra" />
832 <marker date="1515219431000" expanded="true" signature="11397:11483" ph="select * fro... acorn_user_extra" />
833 <marker date="1515219431000" expanded="true" signature="11914:11983" ph="select * fro... subAccount_user_extra" />
834 <marker date="1515219431000" expanded="true" signature="11914:11984" ph="select * fro... subAccount_user_extra" />
835 <marker date="1515219431000" expanded="true" signature="11914:11988" ph="select * fro... subAccount_user_extra" />
836 <marker date="1515219431000" expanded="true" signature="12023:12092" ph="select * fro... subAccount_user_extra" />
837 <marker date="1515219431000" expanded="true" signature="12023:12122" ph="select * fro... subAccount_user_extra" />
838 <marker date="1515219431000" expanded="true" signature="12023:12138" ph="select * fro... subAccount_user_extra" />
839 <marker date="1515219431000" expanded="true" signature="13348:13448" ph="select * fro... ozing_student" />
840 <marker date="1515219431000" expanded="true" signature="13550:13636" ph="update acorn... " />
841 <marker date="1515219431000" expanded="true" signature="13550:13638" ph="update acorn... " />
842 <marker date="1515219431000" expanded="true" signature="13726:13834" ph="select * fro... ozing_student" />
843 <marker date="1515219431000" expanded="true" signature="15966:16006" ph="select max(i... acorn_user" />
844 <marker date="1515219431000" expanded="true" signature="15966:16008" ph="select max(i... acorn_user" />
845 <marker date="1515219431000" expanded="true" signature="16721:16796" ph="select passw... parents_space_pass" />
846 <marker date="1515219431000" expanded="true" signature="17752:17804" ph="update analy... " />
847 <marker date="1515219431000" expanded="true" signature="17752:17821" ph="update analy... " />
848 <marker date="1515219431000" expanded="true" signature="17752:17849" ph="update analy... " />
849 <marker date="1515219431000" expanded="true" signature="17752:17850" ph="update analy... " />
850 </folding>
851 </state>
852 </provider>
853 </entry>
854 <entry file="file://$PROJECT_DIR$/test_cases/debugggggg.py">
855 <provider selected="true" editor-type-id="text-editor">
856 <state relative-caret-position="34">
857 <caret line="2" column="0" lean-forward="false" selection-start-line="2" selection-start-column="0" selection-end-line="2" selection-end-column="0" />
858 <folding />
859 </state>
860 </provider>
861 </entry>
862 <entry file="file://$PROJECT_DIR$/test_cases/app_record_statistic.py">
863 <provider selected="true" editor-type-id="text-editor">
864 <state relative-caret-position="761">
865 <caret line="170" column="45" lean-forward="false" selection-start-line="170" selection-start-column="45" selection-end-line="170" selection-end-column="45" />
866 <folding>
867 <element signature="e#47#62#0" expanded="true" />
868 </folding>
869 </state>
870 </provider>
871 </entry>
872 <entry file="file://$PROJECT_DIR$/test_cases/__init__.py">
873 <provider selected="true" editor-type-id="text-editor">
874 <state relative-caret-position="0">
875 <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
876 <folding />
877 </state>
878 </provider>
879 </entry>
880 <entry file="file://$PROJECT_DIR$/data_fixture/__init__.py">
881 <provider selected="true" editor-type-id="text-editor">
882 <state relative-caret-position="0">
883 <caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
884 <folding />
885 </state>
886 </provider>
887 </entry>
888 <entry file="file://$PROJECT_DIR$/data_fixture/mysql_db.py">
889 <provider selected="true" editor-type-id="text-editor">
890 <state relative-caret-position="34">
891 <caret line="2" column="0" lean-forward="true" selection-start-line="2" selection-start-column="0" selection-end-line="2" selection-end-column="0" />
892 <folding>
893 <marker date="1514616463000" expanded="true" signature="1672:1692" ph="select * fro... " />
894 <marker date="1514616463000" expanded="true" signature="1672:1694" ph="select * fro... missing_value" />
895 <marker date="1514616463000" expanded="true" signature="1672:1718" ph="select count... missing_value" />
896 <marker date="1514616463000" expanded="true" signature="1672:1719" ph="select count... missing_value" />
897 </folding>
898 </state>
899 </provider>
900 </entry>
901 <entry file="file://$PROJECT_DIR$/test_cases/subject_sync.py">
902 <provider selected="true" editor-type-id="text-editor">
903 <state relative-caret-position="85">
904 <caret line="5" column="66" lean-forward="true" selection-start-line="5" selection-start-column="66" selection-end-line="5" selection-end-column="66" />
905 <folding />
906 </state>
907 </provider>
908 </entry>
909 <entry file="file://$PROJECT_DIR$/run_test.py">
910 <provider selected="true" editor-type-id="text-editor">
911 <state relative-caret-position="289">
912 <caret line="17" column="0" lean-forward="true" selection-start-line="17" selection-start-column="0" selection-end-line="17" selection-end-column="0" />
913 <folding>
914 <element signature="e#47#62#0" expanded="true" />
915 </folding>
916 </state>
917 </provider>
918 </entry>
919 </component>
920 </project>
HTMLTestRunner.py
File was created 1 # -*- coding: utf-8 -*-
2
3 """
4 A TestRunner for use with the Python unit testing framework. It
5 generates a HTML report to show the result at a glance.
6
7 The simplest way to use this is to invoke its main method. E.g.
8
9 import unittest
10 import HTMLTestRunner
11
12 ... define your tests ...
13
14 if __name__ == '__main__':
15 HTMLTestRunner.main()
16
17
18 For more customization options, instantiates a HTMLTestRunner object.
19 HTMLTestRunner is a counterpart to unittest's TextTestRunner. E.g.
20
21 # output to a file
22 fp = file('my_report.html', 'wb')
23 runner = HTMLTestRunner.HTMLTestRunner(
24 stream=fp,
25 title='My unit test',
26 description='This demonstrates the report output by HTMLTestRunner.'
27 )
28
29 # Use an external stylesheet.
30 # See the Template_mixin class for more customizable options
31 runner.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">'
32
33 # run the test
34 runner.run(my_test_suite)
35
36
37 ------------------------------------------------------------------------
38 Copyright (c) 2004-2007, Wai Yip Tung
39 All rights reserved.
40
41 Redistribution and use in source and binary forms, with or without
42 modification, are permitted provided that the following conditions are
43 met:
44
45 * Redistributions of source code must retain the above copyright notice,
46 this list of conditions and the following disclaimer.
47 * Redistributions in binary form must reproduce the above copyright
48 notice, this list of conditions and the following disclaimer in the
49 documentation and/or other materials provided with the distribution.
50 * Neither the name Wai Yip Tung nor the names of its contributors may be
51 used to endorse or promote products derived from this software without
52 specific prior written permission.
53
54 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
55 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
57 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
58 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
59 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
60 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
61 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
62 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
63 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
64 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65 """
66
67 # URL: http://tungwaiyip.info/software/HTMLTestRunner.html
68
69 __author__ = "Wai Yip Tung"
70 __version__ = "0.8.2"
71
72
73 """
74 Change History
75
76 Version 0.8.2
77 * Show output inline instead of popup window (Viorel Lupu).
78
79 Version in 0.8.1
80 * Validated XHTML (Wolfgang Borgert).
81 * Added description of test classes and test cases.
82
83 Version in 0.8.0
84 * Define Template_mixin class for customization.
85 * Workaround a IE 6 bug that it does not treat <script> block as CDATA.
86
87 Version in 0.7.1
88 * Back port to Python 2.3 (Frank Horowitz).
89 * Fix missing scroll bars in detail log (Podi).
90 """
91
92 # TODO: color stderr
93 # TODO: simplify javascript using ,ore than 1 class in the class attribute?
94
95 import datetime
96 import io
97 import sys
98 import time
99 import unittest
100 from xml.sax import saxutils
101
102
103 # ------------------------------------------------------------------------
104 # The redirectors below are used to capture output during testing. Output
105 # sent to sys.stdout and sys.stderr are automatically captured. However
106 # in some cases sys.stdout is already cached before HTMLTestRunner is
107 # invoked (e.g. calling logging.basicConfig). In order to capture those
108 # output, use the redirectors for the cached stream.
109 #
110 # e.g.
111 # >>> logging.basicConfig(stream=HTMLTestRunner.stdout_redirector)
112 # >>>
113
114 class OutputRedirector(object):
115 """ Wrapper to redirect stdout or stderr """
116 def __init__(self, fp):
117 self.fp = fp
118
119 def write(self, s):
120 self.fp.write(s)
121
122 def writelines(self, lines):
123 self.fp.writelines(lines)
124
125 def flush(self):
126 self.fp.flush()
127
128 stdout_redirector = OutputRedirector(sys.stdout)
129 stderr_redirector = OutputRedirector(sys.stderr)
130
131
132
133 # ----------------------------------------------------------------------
134 # Template
135
136 class Template_mixin(object):
137 """
138 Define a HTML template for report customerization and generation.
139
140 Overall structure of an HTML report
141
142 HTML
143 +------------------------+
144 |<html> |
145 | <head> |
146 | |
147 | STYLESHEET |
148 | +----------------+ |
149 | | | |
150 | +----------------+ |
151 | |
152 | </head> |
153 | |
154 | <body> |
155 | |
156 | HEADING |
157 | +----------------+ |
158 | | | |
159 | +----------------+ |
160 | |
161 | REPORT |
162 | +----------------+ |
163 | | | |
164 | +----------------+ |
165 | |
166 | ENDING |
167 | +----------------+ |
168 | | | |
169 | +----------------+ |
170 | |
171 | </body> |
172 |</html> |
173 +------------------------+
174 """
175
176 STATUS = {
177 0: 'pass',
178 1: 'fail',
179 2: 'error',
180 }
181
182 DEFAULT_TITLE = 'Unit Test Report'
183 DEFAULT_DESCRIPTION = ''
184
185 # ------------------------------------------------------------------------
186 # HTML Template
187
188 HTML_TMPL = r"""<?xml version="1.0" encoding="UTF-8"?>
189 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
190 <html xmlns="http://www.w3.org/1999/xhtml">
191 <head>
192 <title>%(title)s</title>
193 <meta name="generator" content="%(generator)s"/>
194 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
195 %(stylesheet)s
196 </head>
197 <body>
198 <script language="javascript" type="text/javascript"><!--
199 output_list = Array();
200
201 /* level - 0:Summary; 1:Failed; 2:All */
202 function showCase(level) {
203 trs = document.getElementsByTagName("tr");
204 for (var i = 0; i < trs.length; i++) {
205 tr = trs[i];
206 id = tr.id;
207 if (id.substr(0,2) == 'ft') {
208 if (level < 1) {
209 tr.className = 'hiddenRow';
210 }
211 else {
212 tr.className = '';
213 }
214 }
215 if (id.substr(0,2) == 'pt') {
216 if (level > 1) {
217 tr.className = '';
218 }
219 else {
220 tr.className = 'hiddenRow';
221 }
222 }
223 }
224 }
225
226
227 function showClassDetail(cid, count) {
228 var id_list = Array(count);
229 var toHide = 1;
230 for (var i = 0; i < count; i++) {
231 tid0 = 't' + cid.substr(1) + '.' + (i+1);
232 tid = 'f' + tid0;
233 tr = document.getElementById(tid);
234 if (!tr) {
235 tid = 'p' + tid0;
236 tr = document.getElementById(tid);
237 }
238 id_list[i] = tid;
239 if (tr.className) {
240 toHide = 0;
241 }
242 }
243 for (var i = 0; i < count; i++) {
244 tid = id_list[i];
245 if (toHide) {
246 document.getElementById('div_'+tid).style.display = 'none'
247 document.getElementById(tid).className = 'hiddenRow';
248 }
249 else {
250 document.getElementById(tid).className = '';
251 }
252 }
253 }
254
255
256 function showTestDetail(div_id){
257 var details_div = document.getElementById(div_id)
258 var displayState = details_div.style.display
259 // alert(displayState)
260 if (displayState != 'block' ) {
261 displayState = 'block'
262 details_div.style.display = 'block'
263 }
264 else {
265 details_div.style.display = 'none'
266 }
267 }
268
269
270 function html_escape(s) {
271 s = s.replace(/&/g,'&amp;');
272 s = s.replace(/</g,'&lt;');
273 s = s.replace(/>/g,'&gt;');
274 return s;
275 }
276
277 /* obsoleted by detail in <div>
278 function showOutput(id, name) {
279 var w = window.open("", //url
280 name,
281 "resizable,scrollbars,status,width=800,height=450");
282 d = w.document;
283 d.write("<pre>");
284 d.write(html_escape(output_list[id]));
285 d.write("\n");
286 d.write("<a href='javascript:window.close()'>close</a>\n");
287 d.write("</pre>\n");
288 d.close();
289 }
290 */
291 --></script>
292
293 %(heading)s
294 %(report)s
295 %(ending)s
296
297 </body>
298 </html>
299 """
300 # variables: (title, generator, stylesheet, heading, report, ending)
301
302
303 # ------------------------------------------------------------------------
304 # Stylesheet
305 #
306 # alternatively use a <link> for external style sheet, e.g.
307 # <link rel="stylesheet" href="$url" type="text/css">
308
309 STYLESHEET_TMPL = """
310 <style type="text/css" media="screen">
311 body { font-family: verdana, arial, helvetica, sans-serif; font-size: 80%; }
312 table { font-size: 100%; }
313 pre { }
314
315 /* -- heading ---------------------------------------------------------------------- */
316 h1 {
317 font-size: 16pt;
318 color: gray;
319 }
320 .heading {
321 margin-top: 0ex;
322 margin-bottom: 1ex;
323 }
324
325 .heading .attribute {
326 margin-top: 1ex;
327 margin-bottom: 0;
328 }
329
330 .heading .description {
331 margin-top: 4ex;
332 margin-bottom: 6ex;
333 }
334
335 /* -- css div popup ------------------------------------------------------------------------ */
336 a.popup_link {
337 }
338
339 a.popup_link:hover {
340 color: red;
341 }
342
343 .popup_window {
344 display: none;
345 position: relative;
346 left: 0px;
347 top: 0px;
348 /*border: solid #627173 1px; */
349 padding: 10px;
350 background-color: #E6E6D6;
351 font-family: "Lucida Console", "Courier New", Courier, monospace;
352 text-align: left;
353 font-size: 8pt;
354 width: 500px;
355 }
356
357 }
358 /* -- report ------------------------------------------------------------------------ */
359 #show_detail_line {
360 margin-top: 3ex;
361 margin-bottom: 1ex;
362 }
363 #result_table {
364 width: 80%;
365 border-collapse: collapse;
366 border: 1px solid #777;
367 }
368 #header_row {
369 font-weight: bold;
370 color: white;
371 background-color: #777;
372 }
373 #result_table td {
374 border: 1px solid #777;
375 padding: 2px;
376 }
377 #total_row { font-weight: bold; }
378 .passClass { background-color: #6c6; }
379 .failClass { background-color: #c60; }
380 .errorClass { background-color: #c00; }
381 .passCase { color: #6c6; }
382 .failCase { color: #c60; font-weight: bold; }
383 .errorCase { color: #c00; font-weight: bold; }
384 .hiddenRow { display: none; }
385 .testcase { margin-left: 2em; }
386
387
388 /* -- ending ---------------------------------------------------------------------- */
389 #ending {
390 }
391
392 </style>
393 """
394
395
396
397 # ------------------------------------------------------------------------
398 # Heading
399 #
400
401 HEADING_TMPL = """<div class='heading'>
402 <h1>%(title)s</h1>
403 %(parameters)s
404 <p class='description'>%(description)s</p>
405 </div>
406
407 """ # variables: (title, parameters, description)
408
409 HEADING_ATTRIBUTE_TMPL = """<p class='attribute'><strong>%(name)s:</strong> %(value)s</p>
410 """ # variables: (name, value)
411
412
413
414 # ------------------------------------------------------------------------
415 # Report
416 #
417
418 REPORT_TMPL = """
419 <p id='show_detail_line'>Show
420 <a href='javascript:showCase(0)'>Summary</a>
421 <a href='javascript:showCase(1)'>Failed</a>
422 <a href='javascript:showCase(2)'>All</a>
423 </p>
424 <table id='result_table'>
425 <colgroup>
426 <col align='left' />
427 <col align='right' />
428 <col align='right' />
429 <col align='right' />
430 <col align='right' />
431 <col align='right' />
432 </colgroup>
433 <tr id='header_row'>
434 <td>Test Group/Test case</td>
435 <td>Count</td>
436 <td>Pass</td>
437 <td>Fail</td>
438 <td>Error</td>
439 <td>View</td>
440 </tr>
441 %(test_list)s
442 <tr id='total_row'>
443 <td>Total</td>
444 <td>%(count)s</td>
445 <td>%(Pass)s</td>
446 <td>%(fail)s</td>
447 <td>%(error)s</td>
448 <td>&nbsp;</td>
449 </tr>
450 </table>
451 """ # variables: (test_list, count, Pass, fail, error)
452
453 REPORT_CLASS_TMPL = r"""
454 <tr class='%(style)s'>
455 <td>%(desc)s</td>
456 <td>%(count)s</td>
457 <td>%(Pass)s</td>
458 <td>%(fail)s</td>
459 <td>%(error)s</td>
460 <td><a href="javascript:showClassDetail('%(cid)s',%(count)s)">Detail</a></td>
461 </tr>
462 """ # variables: (style, desc, count, Pass, fail, error, cid)
463
464
465 REPORT_TEST_WITH_OUTPUT_TMPL = r"""
466 <tr id='%(tid)s' class='%(Class)s'>
467 <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
468 <td colspan='5' align='center'>
469
470 <!--css div popup start-->
471 <a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_%(tid)s')" >
472 %(status)s</a>
473
474 <div id='div_%(tid)s' class="popup_window">
475 <div style='text-align: right; color:red;cursor:pointer'>
476 <a onfocus='this.blur();' onclick="document.getElementById('div_%(tid)s').style.display = 'none' " >
477 [x]</a>
478 </div>
479 <pre>
480 %(script)s
481 </pre>
482 </div>
483 <!--css div popup end-->
484
485 </td>
486 </tr>
487 """ # variables: (tid, Class, style, desc, status)
488
489
490 REPORT_TEST_NO_OUTPUT_TMPL = r"""
491 <tr id='%(tid)s' class='%(Class)s'>
492 <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
493 <td colspan='5' align='center'>%(status)s</td>
494 </tr>
495 """ # variables: (tid, Class, style, desc, status)
496
497
498 REPORT_TEST_OUTPUT_TMPL = r"""
499 %(id)s: %(output)s
500 """ # variables: (id, output)
501
502
503
504 # ------------------------------------------------------------------------
505 # ENDING
506 #
507
508 ENDING_TMPL = """<div id='ending'>&nbsp;</div>"""
509
510 # -------------------- The end of the Template class -------------------
511
512
513 TestResult = unittest.TestResult
514
515 class _TestResult(TestResult):
516 # note: _TestResult is a pure representation of results.
517 # It lacks the output and reporting ability compares to unittest._TextTestResult.
518
519 def __init__(self, verbosity=1):
520 TestResult.__init__(self)
521 self.stdout0 = None
522 self.stderr0 = None
523 self.success_count = 0
524 self.failure_count = 0
525 self.error_count = 0
526 self.verbosity = verbosity
527
528 # result is a list of result in 4 tuple
529 # (
530 # result code (0: success; 1: fail; 2: error),
531 # TestCase object,
532 # Test output (byte string),
533 # stack trace,
534 # )
535 self.result = []
536
537
538 def startTest(self, test):
539 TestResult.startTest(self, test)
540 # just one buffer for both stdout and stderr
541 self.outputBuffer = io.StringIO()
542 stdout_redirector.fp = self.outputBuffer
543 stderr_redirector.fp = self.outputBuffer
544 self.stdout0 = sys.stdout
545 self.stderr0 = sys.stderr
546 sys.stdout = stdout_redirector
547 sys.stderr = stderr_redirector
548
549
550 def complete_output(self):
551 """
552 Disconnect output redirection and return buffer.
553 Safe to call multiple times.
554 """
555 if self.stdout0:
556 sys.stdout = self.stdout0
557 sys.stderr = self.stderr0
558 self.stdout0 = None
559 self.stderr0 = None
560 return self.outputBuffer.getvalue()
561
562
563 def stopTest(self, test):
564 # Usually one of addSuccess, addError or addFailure would have been called.
565 # But there are some path in unittest that would bypass this.
566 # We must disconnect stdout in stopTest(), which is guaranteed to be called.
567 self.complete_output()
568
569
570 def addSuccess(self, test):
571 self.success_count += 1
572 TestResult.addSuccess(self, test)
573 output = self.complete_output()
574 self.result.append((0, test, output, ''))
575 if self.verbosity > 1:
576 sys.stderr.write('ok ')
577 sys.stderr.write(str(test))
578 sys.stderr.write('\n')
579 else:
580 sys.stderr.write('.')
581
582 def addError(self, test, err):
583 self.error_count += 1
584 TestResult.addError(self, test, err)
585 _, _exc_str = self.errors[-1]
586 output = self.complete_output()
587 self.result.append((2, test, output, _exc_str))
588 if self.verbosity > 1:
589 sys.stderr.write('E ')
590 sys.stderr.write(str(test))
591 sys.stderr.write('\n')
592 else:
593 sys.stderr.write('E')
594
595 def addFailure(self, test, err):
596 self.failure_count += 1
597 TestResult.addFailure(self, test, err)
598 _, _exc_str = self.failures[-1]
599 output = self.complete_output()
600 self.result.append((1, test, output, _exc_str))
601 if self.verbosity > 1:
602 sys.stderr.write('F ')
603 sys.stderr.write(str(test))
604 sys.stderr.write('\n')
605 else:
606 sys.stderr.write('F')
607
608
609 class HTMLTestRunner(Template_mixin):
610 """
611 """
612 #def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None):
613 def __init__(self, outputdir, verbosity=1, title=None, description=None, report_name='test_report.html'):
614 #self.stream = self._create_output_file(outputdir, report_name)
615 self.outputdir = outputdir
616 self.report_name = report_name
617 self.verbosity = verbosity
618 if title is None:
619 self.title = self.DEFAULT_TITLE
620 else:
621 self.title = title
622 if description is None:
623 self.description = self.DEFAULT_DESCRIPTION
624 else:
625 self.description = description
626
627 self.startTime = datetime.datetime.now()
628
629
630 def _create_output_file(self, output, report_name):
631 import os
632 """ Generate the report file in the given path. """
633 current_dir = os.getcwd()
634 dir_to = os.path.join(current_dir, output)
635 if not os.path.exists(dir_to):
636 os.makedirs(dir_to)
637 path_file = os.path.join(dir_to, report_name)
638 return path_file
639
640
641 def run(self, test):
642 "Run the given test case or test suite."
643 result = _TestResult(self.verbosity)
644 test(result)
645 self.stopTime = datetime.datetime.now()
646 self.generateReport(test, result)
647 # print >> sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)
648 print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))
649 return result
650
651
652 def sortResult(self, result_list):
653 # unittest does not seems to run in any particular order.
654 # Here at least we want to group them together by class.
655 rmap = {}
656 classes = []
657 for n,t,o,e in result_list:
658 cls = t.__class__
659 if not cls in rmap:
660 rmap[cls] = []
661 classes.append(cls)
662 rmap[cls].append((n,t,o,e))
663 r = [(cls, rmap[cls]) for cls in classes]
664 return r
665
666
667 def getReportAttributes(self, result):
668 """
669 Return report attributes as a list of (name, value).
670 Override this to add custom attributes.
671 """
672 startTime = str(self.startTime)[:19]
673 duration = str(self.stopTime - self.startTime)
674 status = []
675 if result.success_count: status.append('Pass %s' % result.success_count)
676 if result.failure_count: status.append('Failure %s' % result.failure_count)
677 if result.error_count: status.append('Error %s' % result.error_count )
678 if status:
679 status = ' '.join(status)
680 else:
681 status = 'none'
682 return [
683 ('Start Time', startTime),
684 ('Duration', duration),
685 ('Status', status),
686 ]
687
688
689
690 def _generate_stylesheet(self):
691 return self.STYLESHEET_TMPL
692
693
694 def _generate_heading(self, report_attrs):
695 a_lines = []
696 for name, value in report_attrs:
697 line = self.HEADING_ATTRIBUTE_TMPL % dict(
698 name = saxutils.escape(name),
699 value = saxutils.escape(value),
700 )
701 a_lines.append(line)
702 heading = self.HEADING_TMPL % dict(
703 title = saxutils.escape(self.title),
704 parameters = ''.join(a_lines),
705 description = saxutils.escape(self.description),
706 )
707 return heading
708
709
710 def _generate_report(self, result):
711 rows = []
712 sortedResult = self.sortResult(result.result)
713 for cid, (cls, cls_results) in enumerate(sortedResult):
714 # subtotal for a class
715 np = nf = ne = 0
716 for n,t,o,e in cls_results:
717 if n == 0: np += 1
718 elif n == 1: nf += 1
719 else: ne += 1
720
721 # format class description
722 if cls.__module__ == "__main__":
723 name = cls.__name__
724 else:
725 name = "%s.%s" % (cls.__module__, cls.__name__)
726 doc = cls.__doc__ and cls.__doc__.split("\n")[0] or ""
727 desc = doc and '%s: %s' % (name, doc) or name
728
729 row = self.REPORT_CLASS_TMPL % dict(
730 style = ne > 0 and 'errorClass' or nf > 0 and 'failClass' or 'passClass',
731 desc = desc,
732 count = np+nf+ne,
733 Pass = np,
734 fail = nf,
735 error = ne,
736 cid = 'c%s' % (cid+1),
737 )
738 rows.append(row)
739
740 for tid, (n,t,o,e) in enumerate(cls_results):
741 self._generate_report_test(rows, cid, tid, n, t, o, e)
742
743 report = self.REPORT_TMPL % dict(
744 test_list = ''.join(rows),
745 count = str(result.success_count+result.failure_count+result.error_count),
746 Pass = str(result.success_count),
747 fail = str(result.failure_count),
748 error = str(result.error_count),
749 )
750 return report
751
752
753 def _generate_report_test(self, rows, cid, tid, n, t, o, e):
754 # e.g. 'pt1.1', 'ft1.1', etc
755 has_output = bool(o or e)
756 tid = (n == 0 and 'p' or 'f') + 't%s.%s' % (cid+1,tid+1)
757 name = t.id().split('.')[-1]
758 doc = t.shortDescription() or ""
759 desc = doc and ('%s: %s' % (name, doc)) or name
760 tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL
761
762 # o and e should be byte string because they are collected from stdout and stderr?
763 if isinstance(o,str):
764 # TODO: some problem with 'string_escape': it escape \n and mess up formating
765 # uo = unicode(o.encode('string_escape'))
766 # uo = o.decode('latin-1')
767 uo = e
768 else:
769 uo = o
770 if isinstance(e,str):
771 # TODO: some problem with 'string_escape': it escape \n and mess up formating
772 # ue = unicode(e.encode('string_escape'))
773 # ue = e.decode('latin-1')
774 ue = e
775 else:
776 ue = e
777
778 script = self.REPORT_TEST_OUTPUT_TMPL % dict(
779 id = tid,
780 output = saxutils.escape(str(uo)+ue),
781 )
782
783 row = tmpl % dict(
784 tid = tid,
785 Class = (n == 0 and 'hiddenRow' or 'none'),
786 style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'none'),
787 desc = desc,
788 script = script,
789 status = self.STATUS[n],
790 )
791 rows.append(row)
792 if not has_output:
793 return
794
795 def _generate_ending(self):
796 return self.ENDING_TMPL
797
798
799 def generateReport(self, test, result):
800 report_attrs = self.getReportAttributes(result)
801 generator = 'HTMLTestRunner %s' % __version__
802 stylesheet = self._generate_stylesheet()
803 heading = self._generate_heading(report_attrs)
804 report = self._generate_report(result)
805 ending = self._generate_ending()
806 # output = self.HTML_TMPL % dict(
807 # title = saxutils.escape(self.title),
808 # generator = generator,
809 # stylesheet = stylesheet,
810 # heading = heading,
811 # report = report,
812 # ending = ending,
813 # )
814
815 output = self.HTML_TMPL % dict(
816 title=saxutils.escape(self.title),
817 generator=generator,
818 stylesheet=stylesheet,
819 heading=heading,
820 report=report,
821 ending=ending,
822 )
823
824 path_file = self._create_output_file(self.outputdir, self.report_name)
825 with open(path_file, 'wb') as report_file:
826 report_file.write(output.encode('utf-8'))
827 #report_file.write(output)
828
829
830 ##############################################################################
831 # Facilities for running tests from the command line
832 ##############################################################################
833
834 # Note: Reuse unittest.TestProgram to launch test. In the future we may
835 # build our own launcher to support more specific command line
836 # parameters like test title, CSS, etc.
837 class TestProgram(unittest.TestProgram):
838 """
839 A variation of the unittest.TestProgram. Please refer to the base
840 class for command line parameters.
841 """
842 def runTests(self):
843 # Pick HTMLTestRunner as the default test runner.
844 # base class's testRunner parameter is not useful because it means
845 # we have to instantiate HTMLTestRunner before we know self.verbosity.
846 if self.testRunner is None:
847 self.testRunner = HTMLTestRunner(verbosity=self.verbosity)
848 unittest.TestProgram.runTests(self)
849
850 main = TestProgram
851
852 ##############################################################################
853 # Executing this module from the command line
854 ##############################################################################
855
856 if __name__ == "__main__":
857 main(module=None)
858
HTMLTestRunner.pyc
No preview for this file type
HTMLTestRunner_bak.py
File was created 1 """
2 A TestRunner for use with the Python unit testing framework. It
3 generates a HTML report to show the result at a glance.
4
5 The simplest way to use this is to invoke its main method. E.g.
6
7 import unittest
8 import HTMLTestRunner
9
10 ... define your tests ...
11
12 if __name__ == '__main__':
13 HTMLTestRunner.main()
14
15
16 For more customization options, instantiates a HTMLTestRunner object.
17 HTMLTestRunner is a counterpart to unittest's TextTestRunner. E.g.
18
19 # output to a file
20 fp = file('my_report.html', 'wb')
21 runner = HTMLTestRunner.HTMLTestRunner(
22 stream=fp,
23 title='My unit test',
24 description='This demonstrates the report output by HTMLTestRunner.'
25 )
26
27 # Use an external stylesheet.
28 # See the Template_mixin class for more customizable options
29 runner.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">'
30
31 # run the test
32 runner.run(my_test_suite)
33
34
35 ------------------------------------------------------------------------
36 Copyright (c) 2004-2007, Wai Yip Tung
37 All rights reserved.
38
39 Redistribution and use in source and binary forms, with or without
40 modification, are permitted provided that the following conditions are
41 met:
42
43 * Redistributions of source code must retain the above copyright notice,
44 this list of conditions and the following disclaimer.
45 * Redistributions in binary form must reproduce the above copyright
46 notice, this list of conditions and the following disclaimer in the
47 documentation and/or other materials provided with the distribution.
48 * Neither the name Wai Yip Tung nor the names of its contributors may be
49 used to endorse or promote products derived from this software without
50 specific prior written permission.
51
52 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
53 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
54 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
55 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
56 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
57 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
58 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
59 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
60 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
61 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
62 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63 """
64
65 # URL: http://tungwaiyip.info/software/HTMLTestRunner.html
66
67 __author__ = "Wai Yip Tung"
68 __version__ = "0.8.2"
69
70
71 """
72 Change History
73
74 Version 0.8.2
75 * Show output inline instead of popup window (Viorel Lupu).
76
77 Version in 0.8.1
78 * Validated XHTML (Wolfgang Borgert).
79 * Added description of test classes and test cases.
80
81 Version in 0.8.0
82 * Define Template_mixin class for customization.
83 * Workaround a IE 6 bug that it does not treat <script> block as CDATA.
84
85 Version in 0.7.1
86 * Back port to Python 2.3 (Frank Horowitz).
87 * Fix missing scroll bars in detail log (Podi).
88 """
89
90 # TODO: color stderr
91 # TODO: simplify javascript using ,ore than 1 class in the class attribute?
92
93 import datetime
94 import io
95 import sys
96 import time
97 import unittest
98 from xml.sax import saxutils
99
100
101 # ------------------------------------------------------------------------
102 # The redirectors below are used to capture output during testing. Output
103 # sent to sys.stdout and sys.stderr are automatically captured. However
104 # in some cases sys.stdout is already cached before HTMLTestRunner is
105 # invoked (e.g. calling logging.basicConfig). In order to capture those
106 # output, use the redirectors for the cached stream.
107 #
108 # e.g.
109 # >>> logging.basicConfig(stream=HTMLTestRunner.stdout_redirector)
110 # >>>
111
112 class OutputRedirector(object):
113 """ Wrapper to redirect stdout or stderr """
114 def __init__(self, fp):
115 self.fp = fp
116
117 def write(self, s):
118 self.fp.write(s)
119
120 def writelines(self, lines):
121 self.fp.writelines(lines)
122
123 def flush(self):
124 self.fp.flush()
125
126 stdout_redirector = OutputRedirector(sys.stdout)
127 stderr_redirector = OutputRedirector(sys.stderr)
128
129
130
131 # ----------------------------------------------------------------------
132 # Template
133
134 class Template_mixin(object):
135 """
136 Define a HTML template for report customerization and generation.
137
138 Overall structure of an HTML report
139
140 HTML
141 +------------------------+
142 |<html> |
143 | <head> |
144 | |
145 | STYLESHEET |
146 | +----------------+ |
147 | | | |
148 | +----------------+ |
149 | |
150 | </head> |
151 | |
152 | <body> |
153 | |
154 | HEADING |
155 | +----------------+ |
156 | | | |
157 | +----------------+ |
158 | |
159 | REPORT |
160 | +----------------+ |
161 | | | |
162 | +----------------+ |
163 | |
164 | ENDING |
165 | +----------------+ |
166 | | | |
167 | +----------------+ |
168 | |
169 | </body> |
170 |</html> |
171 +------------------------+
172 """
173
174 STATUS = {
175 0: 'pass',
176 1: 'fail',
177 2: 'error',
178 }
179
180 DEFAULT_TITLE = 'Unit Test Report'
181 DEFAULT_DESCRIPTION = ''
182
183 # ------------------------------------------------------------------------
184 # HTML Template
185
186 HTML_TMPL = r"""<?xml version="1.0" encoding="UTF-8"?>
187 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
188 <html xmlns="http://www.w3.org/1999/xhtml">
189 <head>
190 <title>%(title)s</title>
191 <meta name="generator" content="%(generator)s"/>
192 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
193 %(stylesheet)s
194 </head>
195 <body>
196 <script language="javascript" type="text/javascript"><!--
197 output_list = Array();
198
199 /* level - 0:Summary; 1:Failed; 2:All */
200 function showCase(level) {
201 trs = document.getElementsByTagName("tr");
202 for (var i = 0; i < trs.length; i++) {
203 tr = trs[i];
204 id = tr.id;
205 if (id.substr(0,2) == 'ft') {
206 if (level < 1) {
207 tr.className = 'hiddenRow';
208 }
209 else {
210 tr.className = '';
211 }
212 }
213 if (id.substr(0,2) == 'pt') {
214 if (level > 1) {
215 tr.className = '';
216 }
217 else {
218 tr.className = 'hiddenRow';
219 }
220 }
221 }
222 }
223
224
225 function showClassDetail(cid, count) {
226 var id_list = Array(count);
227 var toHide = 1;
228 for (var i = 0; i < count; i++) {
229 tid0 = 't' + cid.substr(1) + '.' + (i+1);
230 tid = 'f' + tid0;
231 tr = document.getElementById(tid);
232 if (!tr) {
233 tid = 'p' + tid0;
234 tr = document.getElementById(tid);
235 }
236 id_list[i] = tid;
237 if (tr.className) {
238 toHide = 0;
239 }
240 }
241 for (var i = 0; i < count; i++) {
242 tid = id_list[i];
243 if (toHide) {
244 document.getElementById('div_'+tid).style.display = 'none'
245 document.getElementById(tid).className = 'hiddenRow';
246 }
247 else {
248 document.getElementById(tid).className = '';
249 }
250 }
251 }
252
253
254 function showTestDetail(div_id){
255 var details_div = document.getElementById(div_id)
256 var displayState = details_div.style.display
257 // alert(displayState)
258 if (displayState != 'block' ) {
259 displayState = 'block'
260 details_div.style.display = 'block'
261 }
262 else {
263 details_div.style.display = 'none'
264 }
265 }
266
267
268 function html_escape(s) {
269 s = s.replace(/&/g,'&amp;');
270 s = s.replace(/</g,'&lt;');
271 s = s.replace(/>/g,'&gt;');
272 return s;
273 }
274
275 /* obsoleted by detail in <div>
276 function showOutput(id, name) {
277 var w = window.open("", //url
278 name,
279 "resizable,scrollbars,status,width=800,height=450");
280 d = w.document;
281 d.write("<pre>");
282 d.write(html_escape(output_list[id]));
283 d.write("\n");
284 d.write("<a href='javascript:window.close()'>close</a>\n");
285 d.write("</pre>\n");
286 d.close();
287 }
288 */
289 --></script>
290
291 %(heading)s
292 %(report)s
293 %(ending)s
294
295 </body>
296 </html>
297 """
298 # variables: (title, generator, stylesheet, heading, report, ending)
299
300
301 # ------------------------------------------------------------------------
302 # Stylesheet
303 #
304 # alternatively use a <link> for external style sheet, e.g.
305 # <link rel="stylesheet" href="$url" type="text/css">
306
307 STYLESHEET_TMPL = """
308 <style type="text/css" media="screen">
309 body { font-family: verdana, arial, helvetica, sans-serif; font-size: 80%; }
310 table { font-size: 100%; }
311 pre { }
312
313 /* -- heading ---------------------------------------------------------------------- */
314 h1 {
315 font-size: 16pt;
316 color: gray;
317 }
318 .heading {
319 margin-top: 0ex;
320 margin-bottom: 1ex;
321 }
322
323 .heading .attribute {
324 margin-top: 1ex;
325 margin-bottom: 0;
326 }
327
328 .heading .description {
329 margin-top: 4ex;
330 margin-bottom: 6ex;
331 }
332
333 /* -- css div popup ------------------------------------------------------------------------ */
334 a.popup_link {
335 }
336
337 a.popup_link:hover {
338 color: red;
339 }
340
341 .popup_window {
342 display: none;
343 position: relative;
344 left: 0px;
345 top: 0px;
346 /*border: solid #627173 1px; */
347 padding: 10px;
348 background-color: #E6E6D6;
349 font-family: "Lucida Console", "Courier New", Courier, monospace;
350 text-align: left;
351 font-size: 8pt;
352 width: 500px;
353 }
354
355 }
356 /* -- report ------------------------------------------------------------------------ */
357 #show_detail_line {
358 margin-top: 3ex;
359 margin-bottom: 1ex;
360 }
361 #result_table {
362 width: 80%;
363 border-collapse: collapse;
364 border: 1px solid #777;
365 }
366 #header_row {
367 font-weight: bold;
368 color: white;
369 background-color: #777;
370 }
371 #result_table td {
372 border: 1px solid #777;
373 padding: 2px;
374 }
375 #total_row { font-weight: bold; }
376 .passClass { background-color: #6c6; }
377 .failClass { background-color: #c60; }
378 .errorClass { background-color: #c00; }
379 .passCase { color: #6c6; }
380 .failCase { color: #c60; font-weight: bold; }
381 .errorCase { color: #c00; font-weight: bold; }
382 .hiddenRow { display: none; }
383 .testcase { margin-left: 2em; }
384
385
386 /* -- ending ---------------------------------------------------------------------- */
387 #ending {
388 }
389
390 </style>
391 """
392
393
394
395 # ------------------------------------------------------------------------
396 # Heading
397 #
398
399 HEADING_TMPL = """<div class='heading'>
400 <h1>%(title)s</h1>
401 %(parameters)s
402 <p class='description'>%(description)s</p>
403 </div>
404
405 """ # variables: (title, parameters, description)
406
407 HEADING_ATTRIBUTE_TMPL = """<p class='attribute'><strong>%(name)s:</strong> %(value)s</p>
408 """ # variables: (name, value)
409
410
411
412 # ------------------------------------------------------------------------
413 # Report
414 #
415
416 REPORT_TMPL = """
417 <p id='show_detail_line'>Show
418 <a href='javascript:showCase(0)'>Summary</a>
419 <a href='javascript:showCase(1)'>Failed</a>
420 <a href='javascript:showCase(2)'>All</a>
421 </p>
422 <table id='result_table'>
423 <colgroup>
424 <col align='left' />
425 <col align='right' />
426 <col align='right' />
427 <col align='right' />
428 <col align='right' />
429 <col align='right' />
430 </colgroup>
431 <tr id='header_row'>
432 <td>Test Group/Test case</td>
433 <td>Count</td>
434 <td>Pass</td>
435 <td>Fail</td>
436 <td>Error</td>
437 <td>View</td>
438 </tr>
439 %(test_list)s
440 <tr id='total_row'>
441 <td>Total</td>
442 <td>%(count)s</td>
443 <td>%(Pass)s</td>
444 <td>%(fail)s</td>
445 <td>%(error)s</td>
446 <td>&nbsp;</td>
447 </tr>
448 </table>
449 """ # variables: (test_list, count, Pass, fail, error)
450
451 REPORT_CLASS_TMPL = r"""
452 <tr class='%(style)s'>
453 <td>%(desc)s</td>
454 <td>%(count)s</td>
455 <td>%(Pass)s</td>
456 <td>%(fail)s</td>
457 <td>%(error)s</td>
458 <td><a href="javascript:showClassDetail('%(cid)s',%(count)s)">Detail</a></td>
459 </tr>
460 """ # variables: (style, desc, count, Pass, fail, error, cid)
461
462
463 REPORT_TEST_WITH_OUTPUT_TMPL = r"""
464 <tr id='%(tid)s' class='%(Class)s'>
465 <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
466 <td colspan='5' align='center'>
467
468 <!--css div popup start-->
469 <a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_%(tid)s')" >
470 %(status)s</a>
471
472 <div id='div_%(tid)s' class="popup_window">
473 <div style='text-align: right; color:red;cursor:pointer'>
474 <a onfocus='this.blur();' onclick="document.getElementById('div_%(tid)s').style.display = 'none' " >
475 [x]</a>
476 </div>
477 <pre>
478 %(script)s
479 </pre>
480 </div>
481 <!--css div popup end-->
482
483 </td>
484 </tr>
485 """ # variables: (tid, Class, style, desc, status)
486
487
488 REPORT_TEST_NO_OUTPUT_TMPL = r"""
489 <tr id='%(tid)s' class='%(Class)s'>
490 <td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
491 <td colspan='5' align='center'>%(status)s</td>
492 </tr>
493 """ # variables: (tid, Class, style, desc, status)
494
495
496 REPORT_TEST_OUTPUT_TMPL = r"""
497 %(id)s: %(output)s
498 """ # variables: (id, output)
499
500
501
502 # ------------------------------------------------------------------------
503 # ENDING
504 #
505
506 ENDING_TMPL = """<div id='ending'>&nbsp;</div>"""
507
508 # -------------------- The end of the Template class -------------------
509
510
511 TestResult = unittest.TestResult
512
513 class _TestResult(TestResult):
514 # note: _TestResult is a pure representation of results.
515 # It lacks the output and reporting ability compares to unittest._TextTestResult.
516
517 def __init__(self, verbosity=1):
518 TestResult.__init__(self)
519 self.stdout0 = None
520 self.stderr0 = None
521 self.success_count = 0
522 self.failure_count = 0
523 self.error_count = 0
524 self.verbosity = verbosity
525
526 # result is a list of result in 4 tuple
527 # (
528 # result code (0: success; 1: fail; 2: error),
529 # TestCase object,
530 # Test output (byte string),
531 # stack trace,
532 # )
533 self.result = []
534
535
536 def startTest(self, test):
537 TestResult.startTest(self, test)
538 # just one buffer for both stdout and stderr
539 self.outputBuffer = io.StringIO()
540 stdout_redirector.fp = self.outputBuffer
541 stderr_redirector.fp = self.outputBuffer
542 self.stdout0 = sys.stdout
543 self.stderr0 = sys.stderr
544 sys.stdout = stdout_redirector
545 sys.stderr = stderr_redirector
546
547
548 def complete_output(self):
549 """
550 Disconnect output redirection and return buffer.
551 Safe to call multiple times.
552 """
553 if self.stdout0:
554 sys.stdout = self.stdout0
555 sys.stderr = self.stderr0
556 self.stdout0 = None
557 self.stderr0 = None
558 return self.outputBuffer.getvalue()
559
560
561 def stopTest(self, test):
562 # Usually one of addSuccess, addError or addFailure would have been called.
563 # But there are some path in unittest that would bypass this.
564 # We must disconnect stdout in stopTest(), which is guaranteed to be called.
565 self.complete_output()
566
567
568 def addSuccess(self, test):
569 self.success_count += 1
570 TestResult.addSuccess(self, test)
571 output = self.complete_output()
572 self.result.append((0, test, output, ''))
573 if self.verbosity > 1:
574 sys.stderr.write('ok ')
575 sys.stderr.write(str(test))
576 sys.stderr.write('\n')
577 else:
578 sys.stderr.write('.')
579
580 def addError(self, test, err):
581 self.error_count += 1
582 TestResult.addError(self, test, err)
583 _, _exc_str = self.errors[-1]
584 output = self.complete_output()
585 self.result.append((2, test, output, _exc_str))
586 if self.verbosity > 1:
587 sys.stderr.write('E ')
588 sys.stderr.write(str(test))
589 sys.stderr.write('\n')
590 else:
591 sys.stderr.write('E')
592
593 def addFailure(self, test, err):
594 self.failure_count += 1
595 TestResult.addFailure(self, test, err)
596 _, _exc_str = self.failures[-1]
597 output = self.complete_output()
598 self.result.append((1, test, output, _exc_str))
599 if self.verbosity > 1:
600 sys.stderr.write('F ')
601 sys.stderr.write(str(test))
602 sys.stderr.write('\n')
603 else:
604 sys.stderr.write('F')
605
606
607 class HTMLTestRunner(Template_mixin):
608 """
609 """
610 #def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None):
611 def __init__(self, outputdir, verbosity=1, title=None, description=None, report_name='test_report.html'):
612 #self.stream = self._create_output_file(outputdir, report_name)
613 self.outputdir = outputdir
614 self.report_name = report_name
615 self.verbosity = verbosity
616 if title is None:
617 self.title = self.DEFAULT_TITLE
618 else:
619 self.title = title
620 if description is None:
621 self.description = self.DEFAULT_DESCRIPTION
622 else:
623 self.description = description
624
625 self.startTime = datetime.datetime.now()
626
627
628 def _create_output_file(self, output, report_name):
629 import os
630 """ Generate the report file in the given path. """
631 current_dir = os.getcwd()
632 dir_to = os.path.join(current_dir, output)
633 if not os.path.exists(dir_to):
634 os.makedirs(dir_to)
635 path_file = os.path.join(dir_to, report_name)
636 return path_file
637
638
639 def generateReport(self, test, result):
640 report_attrs = self.getReportAttributes(result)
641 generator = 'HTMLTestRunner %s' % __version__
642 stylesheet = self._generate_stylesheet()
643 heading = self._generate_heading(report_attrs)
644 report = self._generate_report(result)
645 ending = self._generate_ending()
646 # output = self.HTML_TMPL % dict(
647 # title = saxutils.escape(self.title),
648 # generator = generator,
649 # stylesheet = stylesheet,
650 # heading = heading,
651 # report = report,
652 # ending = ending,
653 # )
654
655 output = self.HTML_TMPL % dict(
656 title=saxutils.escape(self.title),
657 generator=generator,
658 stylesheet=stylesheet,
659 heading=heading,
660 report=report,
661 ending=ending,
662 )
663 path_file = self._create_output_file(self.outputdir, self.report_name)
664 with open(path_file, 'w') as report_file:
665 report_file.write(output.encode('utf-8'))
666
667
668 def run(self, test):
669 "Run the given test case or test suite."
670 result = _TestResult(self.verbosity)
671 test(result)
672 self.stopTime = datetime.datetime.now()
673 self.generateReport(test, result)
674 # print >> sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)
675 print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))
676 return result
677
678
679 def sortResult(self, result_list):
680 # unittest does not seems to run in any particular order.
681 # Here at least we want to group them together by class.
682 rmap = {}
683 classes = []
684 for n,t,o,e in result_list:
685 cls = t.__class__
686 if not cls in rmap:
687 rmap[cls] = []
688 classes.append(cls)
689 rmap[cls].append((n,t,o,e))
690 r = [(cls, rmap[cls]) for cls in classes]
691 return r
692
693
694 def getReportAttributes(self, result):
695 """
696 Return report attributes as a list of (name, value).
697 Override this to add custom attributes.
698 """
699 startTime = str(self.startTime)[:19]
700 duration = str(self.stopTime - self.startTime)
701 status = []
702 if result.success_count: status.append('Pass %s' % result.success_count)
703 if result.failure_count: status.append('Failure %s' % result.failure_count)
704 if result.error_count: status.append('Error %s' % result.error_count )
705 if status:
706 status = ' '.join(status)
707 else:
708 status = 'none'
709 return [
710 ('Start Time', startTime),
711 ('Duration', duration),
712 ('Status', status),
713 ]
714
715
716
717
718
719
720
721 def _generate_stylesheet(self):
722 return self.STYLESHEET_TMPL
723
724
725 def _generate_heading(self, report_attrs):
726 a_lines = []
727 for name, value in report_attrs:
728 line = self.HEADING_ATTRIBUTE_TMPL % dict(
729 name = saxutils.escape(name),
730 value = saxutils.escape(value),
731 )
732 a_lines.append(line)
733 heading = self.HEADING_TMPL % dict(
734 title = saxutils.escape(self.title),
735 parameters = ''.join(a_lines),
736 description = saxutils.escape(self.description),
737 )
738 return heading
739
740
741 def _generate_report(self, result):
742 rows = []
743 sortedResult = self.sortResult(result.result)
744 for cid, (cls, cls_results) in enumerate(sortedResult):
745 # subtotal for a class
746 np = nf = ne = 0
747 for n,t,o,e in cls_results:
748 if n == 0: np += 1
749 elif n == 1: nf += 1
750 else: ne += 1
751
752 # format class description
753 if cls.__module__ == "__main__":
754 name = cls.__name__
755 else:
756 name = "%s.%s" % (cls.__module__, cls.__name__)
757 doc = cls.__doc__ and cls.__doc__.split("\n")[0] or ""
758 desc = doc and '%s: %s' % (name, doc) or name
759
760 row = self.REPORT_CLASS_TMPL % dict(
761 style = ne > 0 and 'errorClass' or nf > 0 and 'failClass' or 'passClass',
762 desc = desc,
763 count = np+nf+ne,
764 Pass = np,
765 fail = nf,
766 error = ne,
767 cid = 'c%s' % (cid+1),
768 )
769 rows.append(row)
770
771 for tid, (n,t,o,e) in enumerate(cls_results):
772 self._generate_report_test(rows, cid, tid, n, t, o, e)
773
774 report = self.REPORT_TMPL % dict(
775 test_list = ''.join(rows),
776 count = str(result.success_count+result.failure_count+result.error_count),
777 Pass = str(result.success_count),
778 fail = str(result.failure_count),
779 error = str(result.error_count),
780 )
781 return report
782
783
784 def _generate_report_test(self, rows, cid, tid, n, t, o, e):
785 # e.g. 'pt1.1', 'ft1.1', etc
786 has_output = bool(o or e)
787 tid = (n == 0 and 'p' or 'f') + 't%s.%s' % (cid+1,tid+1)
788 name = t.id().split('.')[-1]
789 doc = t.shortDescription() or ""
790 desc = doc and ('%s: %s' % (name, doc)) or name
791 tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL
792
793 # o and e should be byte string because they are collected from stdout and stderr?
794 if isinstance(o,str):
795 # TODO: some problem with 'string_escape': it escape \n and mess up formating
796 # uo = unicode(o.encode('string_escape'))
797 # uo = o.decode('latin-1')
798 uo = e
799 else:
800 uo = o
801 if isinstance(e,str):
802 # TODO: some problem with 'string_escape': it escape \n and mess up formating
803 # ue = unicode(e.encode('string_escape'))
804 # ue = e.decode('latin-1')
805 ue = e
806 else:
807 ue = e
808
809 script = self.REPORT_TEST_OUTPUT_TMPL % dict(
810 id = tid,
811 output = saxutils.escape(str(uo)+ue),
812 )
813
814 row = tmpl % dict(
815 tid = tid,
816 Class = (n == 0 and 'hiddenRow' or 'none'),
817 style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'none'),
818 desc = desc,
819 script = script,
820 status = self.STATUS[n],
821 )
822 rows.append(row)
823 if not has_output:
824 return
825
826 def _generate_ending(self):
827 return self.ENDING_TMPL
828
829
830 ##############################################################################
831 # Facilities for running tests from the command line
832 ##############################################################################
833
834 # Note: Reuse unittest.TestProgram to launch test. In the future we may
835 # build our own launcher to support more specific command line
836 # parameters like test title, CSS, etc.
837 class TestProgram(unittest.TestProgram):
838 """
839 A variation of the unittest.TestProgram. Please refer to the base
840 class for command line parameters.
841 """
842 def runTests(self):
843 # Pick HTMLTestRunner as the default test runner.
844 # base class's testRunner parameter is not useful because it means
845 # we have to instantiate HTMLTestRunner before we know self.verbosity.
846 if self.testRunner is None:
847 self.testRunner = HTMLTestRunner(verbosity=self.verbosity)
848 unittest.TestProgram.runTests(self)
849
850 main = TestProgram
851
852 ##############################################################################
853 # Executing this module from the command line
854 ##############################################################################
855
856 if __name__ == "__main__":
857 main(module=None)
858
File was created 1 API test scripts about APIs in Pad3.o
2
__pycache__/HTMLTestRunner.cpython-36.pyc
No preview for this file type
__pycache__/HTMLTestRunner_bak.cpython-36.pyc
No preview for this file type
__pycache__/configParse.cpython-36.pyc
No preview for this file type
__pycache__/run_test.cpython-36.pyc
No preview for this file type
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import configparser
5 import pymysql.cursors
6 import os
7
8 base_dir = str(os.path.dirname(os.path.dirname(__file__)))
9 config_dir = base_dir.replace('\\', '/')
10 config_path = config_dir + '/config.ini'
11
12 cp = configparser.ConfigParser()
13 cp.read(config_path)
14 DB_host = cp.get('mysqlconf', 'host')
15 DB_port = cp.get('mysqlconf', 'port')
16 DB_username = cp.get('mysqlconf', 'user')
17 DB_password = cp.get('mysqlconf', 'password')
18 DB_dbName = cp.get('mysqlconf', 'db_name')
19
20 userPhone = cp.get('userinfo', 'userPhone')
21 deviceNumber = cp.get('userinfo','deviceNumber')
22 admin_host = 'http://admin.test.hjx.com/'
23 boss_host = 'http://boss.test.hjx.com/'
data_fixture/__pycache__/config_data.cpython-36.pyc
No preview for this file type
data_fixture/__pycache__/create_testdata.cpython-36.pyc
No preview for this file type
data_fixture/__pycache__/mysql_db.cpython-36.pyc
No preview for this file type
data_fixture/config_data.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 # DB connection
5 DB_HOST='115.29.194.25'
6 DB_PORT=3307
7 DB_USERNAME='cloud'
8 DB_PASSWORD='cloud123'
9 DB_DBNAME='acornuser'
10
11
12 # DB_host='192.168.4.135'
13 # DB_port=3306
14 # DB_username='cloud'
15 # DB_password='wQHPo9H6s7'
16 # DB_db_name='acornuser'
17
18 HOST_BOSS = 'http://boss.test.hjx.com'
19 HOST_ADMIN = 'http://admin.test.hjx.com'
20 HOST_STA = 'http://sta.test.hjx.com'
21 HOST_RES = 'http://res.test.hjx.com'
22
23 #USER_ID = '90000000123456'
24
25 USER_ID = '7000000054686773'
26 USER_ID_INCOMPLETE = '7000000054686777' #注册未完成账号
27 USER_ID_VIDEO = '7000000054686773'
28 USER_ID_NO_VIDEO = '7000000054686776'
29 MODEL = 'AAAAA'
30 USER_PHONE = '13811111111' # 注册登陆
31 USER_PHONE_EDIT = '13811111122' # 修改保卡
32 USER_PHONE_CHANGE = '13811111133' # 修改手机号
33 USER_PHONE_CHANGE_EXISTS = '13811111166'
34 USER_PHONE_USED = '13811111144'
35 USER_PHONE_UNUSED = '13811111155'
36
37
38 PARENT_ID = '7000000054686775'
39
40
41 ## 保卡 ------------------------
42 # 客机,已绑定保卡
43 DEVICE_NUMBER_CUS_BIND = 'CUSBIND123456789'
44 MAC_CUS_BIND = '00:00:00:00:00:11'
45 # 客机, 没有保卡
46 DEVICE_NUMBER_CUS_UNBIND = 'CUSUNBIND123456789'
47 MAC_CUS_UNBIND = '00:00:00:00:00:22'
48 # 样机
49 DEVICE_NUMBER_SAM = 'SAM123456789'
50 MAC_SAM = '00:00:00:00:00:33'
51
52 #添加客机保卡
53 DEVICE_NUMBER_NEW = 'NEW123456789'
54 MAC_NEW = '00:00:00:00:00:44'
55
56 # 置为样机,提交终端信息
57 DEVICE_NUMBER_TO_SAM = 'TOSAM123456789'
58
59 #置为客机
60 DEVICE_NUMBER_TO_CUS = 'TOCUS123456789'
61
62 #解绑保卡
63 DEVICE_NUMBER_UNBIND = 'UNBIND123456789'
64
65 #修改保卡
66 DEVICE_NUMBER_EDIT = 'EDIT123456789'
67
68
69 ## 子账户 -----------------------
70 #子账户头像
71 SUB_ACC_IMAGE = 'http://hjxprodbucket.oss.aliyuncs.com/static/upload/boss_api/announcement/2017-08-29/a00de899-2f6d-43fb-9e30-71883842540e.png'
72 #子账户区域
73 SUB_ACC_REGION_NAME_1 = '河北秦皇岛青龙'
74 SUB_ACC_REGION_NAME_2 = '江苏南京玄武'
75 #子账户区域ID
76 SUB_ACC_REGION_ID_1 = 130321
77 SUB_ACC_REGION_ID_2 = 320102
78 #子账户学校ID
79 SUB_ACC_SCHOOL_ID_1 = 43470 ## 小学
80 SUB_ACC_SCHOOL_ID_2 = 500016 ## 中学
81
82
83
84
85
86
data_fixture/create_testdata.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 from data_fixture.mysql_db import DB
5 from data_fixture import config_data as Data
6 from datetime import datetime, date, timedelta
7 import time
8 from data_fixture.config_data import HOST_BOSS
9 import requests
10 import calendar
11 import uuid
12
13
14 db = DB()
15
16 ## *********************************************************************************************************************
17 ## 验证码
18 ## *********************************************************************************************************************
19 def fet_authCode(mobile):
20 url = HOST_BOSS + "/ozing/timer/user/fetchAuthCode"
21 headers = {'Accept': '*/*'}
22 postData = {'mobile': mobile, 'type': 'general'}
23 r = requests.post(url, headers=headers, data=postData)
24 result = r.json()
25 if result['status'] == 100:
26 return result['jsessionid']
27 else :
28 raise FetchException('fetch auth code Error!')
29
30
31 class FetchException(Exception):
32 pass
33
34 ## *********************************************************************************************************************
35 ## 保卡
36 ## *********************************************************************************************************************
37 # 保卡数据 -- 新建保卡
38 def pre_elecCard(device_cus_bind='0', device_sam='0', device_cus_unbind='0'):
39
40 if device_cus_bind != '0':
41 # 客机,已绑定保卡
42 select_customermachine = "select * from acornuser.ozing_customermachine where deviceNumber = '{}' ".format(device_cus_bind)
43 select_machine_cus = "SELECT * FROM acornuser.ozing_machine where deviceNumber = '{}' ".format(device_cus_bind)
44 insert_customermachine_tabel = 'acornuser.ozing_customermachine'
45 insert_customermachine_data = {
46 'deviceNumber': device_cus_bind,
47 'userId': Data.USER_ID,
48 'customerName':'测试customer',
49 'customerAddress':'内蒙古巴彦淖尔市',
50 'customerPhone':'13822222222',
51 'buyTime': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
52 'buyAddress':'内蒙古巴彦淖尔市',
53 'alterSaleCall':'51518888',
54 'cmstate': '1',
55 'createTime': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
56 }
57 insert_machine_cus_table = 'acornuser.ozing_machine'
58 insert_machine_cus_data = {'productModel': Data.MODEL,
59 'deviceNumber': device_cus_bind,
60 'macAddress': Data.MAC_CUS_BIND,
61 'state': '1'
62 }
63 if db.select(select_customermachine):
64 pass
65 else:
66 db.insert(insert_customermachine_tabel, insert_customermachine_data)
67
68 if db.select(select_machine_cus):
69 pass
70 else:
71 db.insert(insert_machine_cus_table, insert_machine_cus_data)
72
73 # 样机
74 if device_sam !='0':
75 select_samplemachine = "SELECT * FROM acornuser.ozing_samplemachine where deviceNumber = '{}' ".format(device_sam)
76 select_machine_sam = "SELECT * FROM acornuser.ozing_machine where deviceNumber = '{}' ".format(device_sam)
77 insert_samplemachine_tabel = 'acornuser.ozing_samplemachine'
78 insert_samplemachine_data= {'deviceNumber': device_sam,
79 'userId': Data.USER_ID,
80 'terminalAddress': "内蒙古巴彦淖尔市",
81 'distributor': "新华书店",
82 'saleClerk':"张三",
83 'mobilePhone': "18622222222",
84 'photo':'[{"photoUrl":"static/upload/online_api/samplePhoto/2017-12-13/b6480129-e720-4109-a455-6130fd640f16.jpg"},{"photoUrl":"static/upload/online_api/samplePhoto/2017-12-13/b8317fa4-cfa5-4ea4-91d4-3ca020e06bca.jpg"},{"photoUrl":"static/upload/online_api/samplePhoto/2017-12-13/110dc30b-34f1-4e0b-88e0-a030b8ab4af7.jpg"}]',
85 'smstate': '1',
86 'createTime': datetime.now().strftime('%Y-%m-%d %H:%M:%S') }
87 insert_machine_sam_tabel = 'acornuser.ozing_machine'
88 insert_machine_sam_data = {'productModel': Data.MODEL,
89 'deviceNumber': device_sam,
90 'macAddress': Data.MAC_SAM,
91 'state': '0'}
92
93 if db.select(select_samplemachine):
94 pass
95 else:
96 db.insert(insert_samplemachine_tabel, insert_samplemachine_data)
97
98 if db.select(select_machine_sam):
99 pass
100 else:
101 db.insert(insert_machine_sam_tabel, insert_machine_sam_data)
102
103 # 未绑定 -- 客机
104 if device_cus_unbind != '0':
105 select_customermachine_unbind = "select * from acornuser.ozing_customermachine where deviceNumber = '{}' " \
106 .format(device_cus_unbind)
107 update_customermachine_unbind_tabel = 'acornuser.ozing_customermachine'
108 update_customermachine_unbind_set = {'deviceNumber':str(time.time())}
109 update_customermachine_unbind_where = {'deviceNumber': device_cus_unbind}
110
111 select_machine_cus_1 = "SELECT * FROM acornuser.ozing_machine where deviceNumber = '{}' ".format(device_cus_unbind)
112 select_machine_cus_2 = "SELECT * FROM acornuser.ozing_machine where deviceNumber = '{}' and state = '1' ".format(device_cus_unbind)
113
114 update_machine_cus_unbind_table = 'acornuser.ozing_machine'
115 update_machine_cus_unbind_set = {'state': '1'}
116 update_machine_cus_unbind_where = {'deviceNumber': device_cus_unbind}
117
118 # 保卡表中有数据
119 if db.select(select_customermachine_unbind):
120 db.update(update_customermachine_unbind_tabel, update_customermachine_unbind_set, update_customermachine_unbind_where)
121 # 机器表中有数据,并且状态是1
122 if db.select(select_machine_cus_1):
123 if db.select(select_machine_cus_2):
124 pass
125 else:
126 # update state =1
127 db.update(update_machine_cus_unbind_table, update_machine_cus_unbind_set, update_machine_cus_unbind_where)
128 # 机器表中没数据
129 else:
130 pass
131
132 # #添加客机保卡
133 def pre_SetUpElecCard():
134 select_customermachine_new = "select * from acornuser.ozing_customermachine where deviceNumber = '{}' ".format(Data.DEVICE_NUMBER_NEW)
135 update_customermachine_new_tabel = 'acornuser.ozing_customermachine'
136 update_customermachine_new_set = {'deviceNumber':str(time.time())}
137 update_customermachine_new_where = {'deviceNumber': Data.DEVICE_NUMBER_NEW}
138
139 select_machine_new = "select * from acornuser.ozing_machine where deviceNumber = '{}' ".format(Data.DEVICE_NUMBER_NEW)
140 update_machine_new_tabel = 'acornuser.ozing_machine'
141 update_machine_new_set = {'deviceNumber': str(time.time())}
142 update_machine_new_where = {'deviceNumber': Data.DEVICE_NUMBER_NEW}
143
144 if db.select(select_customermachine_new):
145 db.update(update_customermachine_new_tabel, update_customermachine_new_set, update_customermachine_new_where)
146 if db.select(select_machine_new):
147 db.update(update_machine_new_tabel, update_machine_new_set, update_machine_new_where)
148
149
150 ## *********************************************************************************************************************
151 ## 子账户
152 ## *********************************************************************************************************************
153
154 def pre_subAccount(parent_id, sub_account_id, status, deviceNumber=Data.DEVICE_NUMBER_CUS_BIND): #status: child status
155
156 # 子账户数据
157 TABEL_CHILD_USER = 'acornuser.child_user'
158 if status == 1 : # make sure only 1 sub account's status marked as '1'
159 update_all_0_sub = "update acornuser.child_user set status = 0 where parent_id = '{}' and deviceNumber = '{}'" \
160 .format(parent_id, deviceNumber)
161 db.update_(update_all_0_sub)
162
163 select_sub_acc = "select * from acornuser.child_user where parent_id = '{}' and subAccountId = '{}' ".format(parent_id, sub_account_id)
164 select_sub_acc_status = "select * from acornuser.child_user where parent_id = '{}' and subAccountId = '{}' " \
165 "and status = {} ".format(parent_id, sub_account_id, status)
166 update_set = {'status': status}
167 update_where = {'subAccountId': sub_account_id }
168 insert_data = {'parent_id':parent_id,
169 'image': Data.SUB_ACC_IMAGE,
170 'name' : '测试sub',
171 'grade_id':'6',
172 'school_id': Data.SUB_ACC_SCHOOL_ID_2,
173 'region_id': Data.SUB_ACC_REGION_ID_2,
174 'status':status,
175 'region_name': Data.SUB_ACC_REGION_NAME_2,
176 'deviceNumber':Data.DEVICE_NUMBER_CUS_BIND,
177 'subAccountId':sub_account_id
178 }
179
180 if db.select(select_sub_acc_status):
181 pass
182 elif db.select(select_sub_acc):
183 db.update(TABEL_CHILD_USER, update_set, update_where)
184 else:
185 db.insert(TABEL_CHILD_USER, insert_data)
186
187
188 #主账户数据
189 select_acc_1 = "select * from acornuser.acorn_user_status where userId = '{}' and deviceNumber = '{}' " \
190 .format(parent_id, deviceNumber)
191 if status == 1: # if child status == 1, parent status should be 0
192 select_acc_2 = "select * from acornuser.acorn_user_status where userId = '{}' and deviceNumber = '{}' and status = 0 " \
193 .format(parent_id, deviceNumber)
194
195 insert_data_parent_0 = {'userId': parent_id,
196 'status': 0,
197 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND
198 }
199 set_0 = {'status': 0}
200 where = {'userId': parent_id,
201 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND
202 }
203
204 if db.select(select_acc_2):
205 pass
206 elif db.select(select_acc_1):
207 db.update("acornuser.acorn_user_status", set_0, where)
208 else:
209 db.insert("acornuser.acorn_user_status", insert_data_parent_0)
210 else: # if child status == 0, parent status should be 1
211 select_acc_3 = "select * from acornuser.acorn_user_status where userId = '{}' and deviceNumber = '{}' and status = 1 " \
212 .format(parent_id, deviceNumber)
213 set_1 = {'status': 1}
214 where = {'userId': parent_id,
215 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND
216 }
217 insert_data_parent_1 = {'userId': parent_id,
218 'status': 1,
219 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND
220 }
221 if db.select(select_acc_3):
222 pass
223 elif db.select(select_acc_1):
224 db.update("acornuser.acorn_user_status", set_1, where)
225 else:
226 db.insert("acornuser.acorn_user_status", insert_data_parent_1)
227
228
229
230
231 # 删除对应的parentID的所有数据 便于验证添加成功
232 def pre_AddSubAccount(parent_Id):
233 where_data = {'parent_Id': parent_Id}
234 set_data = {'parent_Id': calendar.timegm(time.gmtime())}
235 if db.select_('acornuser.child_user', where_data):
236 db.update('acornuser.child_user', set_data, where_data)
237
238
239 #检查signature存在
240 def checkSignatureExists(userId, type):
241 #主账户
242 if type == 1:
243 sql_1 = 'select * from acornuser.acorn_user_extra where user_id = {} '.format(userId)
244 sql_2 = 'select * from acornuser.acorn_user_extra where user_id = {} and signature is not NULL'.format(userId)
245
246 if db.select(sql_2):
247 pass
248 elif db.select(sql_1):
249 set = {'signature': '聪明的波利'}
250 where = {'user_id': userId}
251 db.update('acornuser.acorn_user_extra', set, where)
252 else:
253 insert = {'user_id': userId, 'signature': '聪明的波利'}
254 db.insert('acornuser.acorn_user_extra', insert)
255
256 # 子账户
257 if type == 2:
258 sql_1 = "select * from acornuser.subAccount_user_extra where sub_account_id = '{}' ".format(userId)
259 sql_2 = "select * from acornuser.subAccount_user_extra where sub_account_id = '{}'and signature is not NULL".format(userId)
260
261 if db.select(sql_2):
262 pass
263 elif db.select(sql_1):
264 set = {'signature': '聪明的波利 sub~'}
265 where = {'sub_account_id': userId}
266 db.update('acornuser.subAccount_user_extra', set, where)
267 else:
268 insert = {'sub_account_id': userId, 'signature': '聪明的波利 sub~'}
269 db.insert('acornuser.subAccount_user_extra', insert)
270
271
272 ## *********************************************************************************************************************
273 ## 教材版本
274 ## *********************************************************************************************************************
275
276 # 用户版本信息
277 def pre_GetUserPressInfo(userId):
278 set = {'chinese': '北京师范大学出版社'}
279 where = {'user_id': userId}
280 db.update('acornuser.user_press', set, where)
281
282
283 ## *********************************************************************************************************************
284 ## 登录注册
285 ## *********************************************************************************************************************
286 # 检查用户注册信息是否完整
287 def pre_register_extrainfo_check(user_id, complete):
288 #不完整
289 if complete == False:
290 sql = "select * from acornuser.ozing_student where user_id = {} and region_id is NULL and school_id is NULL".format(user_id)
291 if db.select(sql):
292 pass
293 else:
294 update_sql = "update acornuser.ozing_student set region_id = NULL, school_id = NULL where user_id = {}".format(user_id)
295 db.update_(update_sql)
296
297 # 完整
298 else:
299 sql = "select * from acornuser.ozing_student where user_id = {} and region_id is not NULL and school_id is not NULL".format(
300 user_id)
301 if db.select(sql):
302 pass
303 else:
304 set = {'region_id': '140600', 'school_id': '496299', 'region_name':'江苏苏州吴中'}
305 where = {'user_id': user_id}
306 db.update('acornuser.ozing_student', set, where)
307
308 ## *********************************************************************************************************************
309 ## 最近观看视频
310 ## *********************************************************************************************************************
311 def pre_getRecentVideo(user_id, status): # status=0 novideo, status=1 has video
312 where = {'user_id': user_id}
313 if status == 0 :
314 set = {'user_id': str(time.time())}
315 if db.select_('acornuser.user_video_watch', where):
316 db.update('acornuser.user_video_watch', set, where)
317
318 if status == 1 :
319 if db.select_('acornuser.user_video_watch', where):
320 pass
321 else:
322 insert_data = {'user_id': user_id,
323 'data_id': 486600,
324 'data_name':'人教7上_1 春_程诗尧.mpc',
325 'play_online_url':'http://fd.xuexiao100.com/mp4/黄冈视频/初中语文/7年级上 人民教育出版社_2017版/人教7上_1 春_程诗尧.mp4?k=e8f8a7429a42aff00cb96faa6f48821e',
326 'cover_url': 'http://hjxprodbucket.oss.aliyuncs.com/static/upload/boss_api/announcement/2017-10-18/34cfe338-2305-4aa0-96d8-c952be4dd800.jpg',
327 'app_unique_name': 'famous-teacher',
328 'created_time': '2017-12-27 14:52:08',
329 'modified_time': '2017-12-27 14:52:08'
330 }
331 db.insert('acornuser.user_video_watch', insert_data)
332
333 ## *********************************************************************************************************************
334 ## 手机号重复验证
335 ## *********************************************************************************************************************
336 def pre_phoneUsedCheck(phone, used): #used = True :used
337 where = {'username': phone}
338 if used:
339 if db.select_('acornuser.acorn_user', where):
340 pass
341 else:
342 max_id = db.select('select max(id) from acornuser.acorn_user')[0]['max(id)']
343 update_where = {'id': max_id - 150}
344 count = db.select_('acornuser.acorn_user', update_where)
345
346 db.update('acornuser.acorn_user', where, update_where)
347 else:
348 if db.select_('acornuser.acorn_user', where):
349 update_set = {'username': str(time.time())}
350 db.update('acornuser.acorn_user', update_set, where)
351
352
353 ## *********************************************************************************************************************
354 ## 家长控制 密码
355 ## *********************************************************************************************************************
356 def get_parentSpace_password(device_number):
357 sql = "select password from acornuser.parents_space_pass where deviceNumber = '{}'".format(device_number)
358 result = db.select(sql)
359 if result:
360 return result[0]['password']
361 else:
362 return '123456'
363
364
365 ## *********************************************************************************************************************
366 ## 家长控制 app使用统计
367 ## *********************************************************************************************************************
368 # "now" format: timestamp , create app using data about this week, month, year, last year(according 'now' time)
369 def create_app_use_record(now, user_id, device_number):
370 today = date.fromtimestamp(now)
371 year_start_time = int(str(time.mktime(date(today.year, 1, 1).timetuple())).split('.')[0])
372 where_equal = {'user_id':user_id, 'device_number':device_number}
373 where_unequal = ' time_end > {} '.format(year_start_time)
374 if db.select_('analytics.app_record', where_equal, where_unequal): # data existing
375 update_data = "update analytics.app_record set device_number = '{}' where user_id = '{}' and device_number = '{}' " \
376 .format(str(time.time()), user_id, device_number)
377 db.update_(update_data)
378 study_apps = [{'app_name':'百度英语资料大全', 'app_pid':'com.sailang.EnglishBook','category_id':'25', 'source_id':'1', \
379 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
380 {'app_name': '开心大学士', 'app_pid': 'com.ksense.study','category_id':'26', 'source_id':'1', \
381 'time_spent': 200, 'user_id': user_id, 'device_number': device_number},
382 {'app_name': '驾考宝典', 'app_pid': 'com.handsgo.jiakao.android' ,'category_id':'27', 'source_id':'1', \
383 'time_spent': 300, 'user_id': user_id, 'device_number': device_number},
384 {'app_name': '我爱汉字', 'app_pid': 'com.cronlygames.hanzi' ,'category_id':'28', 'source_id':'1',\
385 'time_spent': 400, 'user_id': user_id, 'device_number': device_number},
386 {'app_name': '拖拖乐3', 'app_pid': 'cn.com.wiisoft.tuotuo' ,'category_id':'57', 'source_id':'1', \
387 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
388 {'app_name': '幼儿数字算数学习', 'app_pid': 'com.syhrobert1991.infantlearning' ,'category_id':'25', \
389 'source_id':'1', 'time_spent': 200, 'user_id': user_id, 'device_number': device_number},
390 {'app_name': '轻松背单词之初中英语', 'app_pid': 'petpestzx.wordroid.model' ,'category_id':'26', \
391 'source_id':'2', 'time_spent': 300, 'user_id': user_id, 'device_number': device_number},
392 {'app_name': '有谱-爱学习(数理化)', 'app_pid': 'com.emingren.youpu' ,'category_id':'27', 'source_id':'2', \
393 'time_spent': 400, 'user_id': user_id, 'device_number': device_number},
394 {'app_name': '疯狂音标', 'app_pid': 'com.neo.crazyphonetic' ,'category_id':'28', 'source_id':'2', \
395 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
396 {'app_name': '互动作业V3.18.6', 'app_pid': 'com.v.study' ,'category_id':'57', 'source_id':'2', \
397 'time_spent': 250, 'user_id': user_id, 'device_number': device_number},
398 {'app_name': '发音背单词', 'app_pid': 'org.liberty.android.fantastischmemo' ,'category_id':'57', \
399 'source_id':'2', 'time_spent': 350, 'user_id': user_id, 'device_number': device_number},
400 {'app_name': '语文100', 'app_pid': 'com.kk.kkyuwen' ,'category_id':'57', 'source_id':'2', \
401 'time_spent': 450, 'user_id': user_id, 'device_number': device_number}
402 ]
403
404 game_apps = [{'app_name': '小伴龙新', 'app_pid': 'com.xiaobanlong.main' ,'category_id':'37', 'source_id':'1',\
405 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
406 {'app_name': '三国群英传', 'app_pid': 'com.tencent.tmgp.sgqyz' ,'category_id':'38', 'source_id':'1', \
407 'time_spent': 200, 'user_id': user_id, 'device_number': device_number},
408 {'app_name': '童言童语', 'app_pid': 'com.lingshi.kids' ,'category_id':'39', 'source_id':'2', \
409 'time_spent': 300, 'user_id': user_id, 'device_number': device_number},
410 {'app_name': '从前啊', 'app_pid': 'com.mojie.longlongago' ,'category_id':'37', 'source_id':'2', \
411 'time_spent': 400, 'user_id': user_id, 'device_number': device_number},
412 {'app_name': '永恒纪元', 'app_pid': 'com.m37.dtszj.uc' ,'category_id':'38', 'source_id':'2', \
413 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
414 {'app_name': '我的世界新', 'app_pid': 'com.netease.mc.aligames' ,'category_id':'39', 'source_id':'2', \
415 'time_spent': 200, 'user_id': user_id, 'device_number': device_number},
416 {'app_name': '球球大作战', 'app_pid': 'com.ztgame.bob', 'category_id': '37', 'source_id': '2', \
417 'time_spent': 300, 'user_id': user_id, 'device_number': device_number},
418 {'app_name': '葫芦侠我的世界', 'app_pid': 'com.huluxia.mctool', 'category_id': '38', 'source_id': '2',\
419 'time_spent': 400, 'user_id': user_id, 'device_number': device_number},
420 {'app_name': 'QQ游戏V6.8.7', 'app_pid': 'com.tencent.qqgame', 'category_id': '39', 'source_id': '2',\
421 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
422 {'app_name': '99围棋最新', 'app_pid': 'com.r99weiqi.dvd', 'category_id': '37', 'source_id': '2', \
423 'time_spent': 50, 'user_id': user_id, 'device_number': device_number},
424 {'app_name': '凯蒂环球之旅', 'app_pid': 'com.tencent.HelloKitty', 'category_id': '37', 'source_id': '2',\
425 'time_spent': 150, 'user_id': user_id, 'device_number': device_number},
426 {'app_name': '贪吃蛇大作战', 'app_pid': 'com.wepie.snake.qihoo', 'category_id': '100', 'source_id': '2',\
427 'time_spent': 250, 'user_id': user_id, 'device_number': device_number}
428 ]
429
430 # get date of the last 7 days(include today)
431 days = [] # the day should insert app records
432 if today.month == 1: # the first month of this year
433 if today.day <= 7: # when today < 7th day of this month , 7 records chould cover this week ,this month, this year
434 for i in range(0, 7):
435 day_delta = timedelta(days=i)
436 days.append(str(time.mktime((today - day_delta).timetuple())).split('.')[0])
437 else: # when today > 7th day of this month , should create 8 records to cover this week ,this month, this year
438 for i in range(0, 8):
439 day_delta = timedelta(days=i)
440 days.append(str(time.mktime((today - day_delta).timetuple())).split('.')[0])
441 else: # create january data to cover this year
442 for i in range(0, 8):
443 day_delta = timedelta(days=i)
444 days.append(str(time.mktime((today - day_delta).timetuple())).split('.')[0])
445 days.append(str(time.mktime(date(today.year, 1, 1).timetuple())).split('.')[0])
446
447
448 app_rec_to_insert = []
449 for day in days:
450 for i in range(0, 12):
451 time_end_1 = {'time_end': int(day) + 28800 + i * 1000, 'id':str(uuid.uuid4()).replace('-', '')}
452 time_end_2 = {'time_end': int(day) + 29800 + i * 500, 'id':str(uuid.uuid4()).replace('-', '')}
453 study_app = study_apps[i].copy()
454 study_app.update(time_end_1)
455 game_app = game_apps[i].copy()
456 game_app.update(time_end_2)
457 app_rec_to_insert.append(study_app)
458 app_rec_to_insert.append(game_app)
459
460 for rec in app_rec_to_insert:
461 db.insert('analytics.app_record', rec)
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
data_fixture/mysql_db.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import configparser
5 import pymysql.cursors
6 import os
7
8 from . import config_data as Data
9 #
10 # base_dir = str(os.path.dirname(os.path.dirname(__file__)))
11 # config_dir = base_dir.replace('\\', '/')
12 # config_path = config_dir + '/config.ini'
13 #
14 # cp = configparser.ConfigParser()
15 # cp.read(config_path)
16 # DB_host = cp.get('mysqlconf', 'host')
17 # DB_port = cp.get('mysqlconf', 'port')
18 # DB_username = cp.get('mysqlconf', 'user')
19 # DB_password = cp.get('mysqlconf', 'password')
20 # DB_dbName = cp.get('mysqlconf', 'db_name')
21
22
23 class DB:
24
25 def __init__ (self):
26 try:
27 self.connection = pymysql.connect(host=Data.DB_HOST,
28 port=Data.DB_PORT,
29 user=Data.DB_USERNAME,
30 password=Data.DB_PASSWORD,
31 charset='utf8mb4',
32 cursorclass=pymysql.cursors.DictCursor
33 )
34 except pymysql.err.OperationalError as e:
35 print ("MySql error %d: %s" % (e.args[0], e.args[1]))
36
37 def select(self, sql):
38 with self.connection.cursor() as cursor:
39 if cursor.execute(sql):
40 return cursor.fetchall()
41 else:
42 return None
43
44 def select_(self, tabel_name, where_data_equal, where_data_unequal = None ):
45 sql_where = ' and '.join("{} = '{}' ".format(key, value) for (key, value) in where_data_equal.items())
46 if where_data_unequal:
47 sql_where = sql_where + ' and ' + where_data_unequal
48 sql = 'select count(1) from ' + tabel_name + ' where ' + sql_where
49 with self.connection.cursor() as cursor:
50 cursor.execute(sql)
51 result = cursor.fetchone()
52 return result['count(1)']
53
54
55 def insert(self, table_name, table_data):
56 for key in table_data:
57 table_data[key] = " '" + str(table_data[key]) + "'"
58 key = ','.join(table_data.keys())
59 value = ','.join(table_data.values())
60 real_sql = 'INSERT INTO ' + table_name + " (" + key + " ) VALUES ( "\
61 + value + " )"
62 with self.connection.cursor() as cursor:
63 cursor.execute(real_sql)
64 self.connection.commit()
65
66 def update(self, table_name, set_data, where_data):
67 sql_set = ','.join("{}='{}'".format(key, value) for (key, value) in set_data.items())
68 sql_where = ' and '.join("{}='{}'".format(key, value) for (key, value) in where_data.items())
69 print(sql_set, sql_where)
70 real_sql = "UPDATE " + table_name + " SET " + sql_set + " WHERE " + sql_where
71
72 with self.connection.cursor() as cursor:
73 cursor.execute(real_sql)
74 self.connection.commit()
75
76
77 def update_(self, sql):
78 with self.connection.cursor() as cursor:
79 cursor.execute(sql)
80 self.connection.commit()
81
82
83 def close(self):
84 self.connection.close()
85
86
87
88
data_fixture/test_verify.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 from data_fixture.mysql_db import DB
5 from data_fixture import config_data as Data
6 from datetime import datetime
7 import time
8 from data_fixture.config_data import HOST_BOSS
9 import requests
10
11
12
report/test_report.html
File was created 1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
5 <title>Unit Test Report</title>
6 <meta name="generator" content="HTMLTestRunner 0.8.2"/>
7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
8
9 <style type="text/css" media="screen">
10 body { font-family: verdana, arial, helvetica, sans-serif; font-size: 80%; }
11 table { font-size: 100%; }
12 pre { }
13
14 /* -- heading ---------------------------------------------------------------------- */
15 h1 {
16 font-size: 16pt;
17 color: gray;
18 }
19 .heading {
20 margin-top: 0ex;
21 margin-bottom: 1ex;
22 }
23
24 .heading .attribute {
25 margin-top: 1ex;
26 margin-bottom: 0;
27 }
28
29 .heading .description {
30 margin-top: 4ex;
31 margin-bottom: 6ex;
32 }
33
34 /* -- css div popup ------------------------------------------------------------------------ */
35 a.popup_link {
36 }
37
38 a.popup_link:hover {
39 color: red;
40 }
41
42 .popup_window {
43 display: none;
44 position: relative;
45 left: 0px;
46 top: 0px;
47 /*border: solid #627173 1px; */
48 padding: 10px;
49 background-color: #E6E6D6;
50 font-family: "Lucida Console", "Courier New", Courier, monospace;
51 text-align: left;
52 font-size: 8pt;
53 width: 500px;
54 }
55
56 }
57 /* -- report ------------------------------------------------------------------------ */
58 #show_detail_line {
59 margin-top: 3ex;
60 margin-bottom: 1ex;
61 }
62 #result_table {
63 width: 80%;
64 border-collapse: collapse;
65 border: 1px solid #777;
66 }
67 #header_row {
68 font-weight: bold;
69 color: white;
70 background-color: #777;
71 }
72 #result_table td {
73 border: 1px solid #777;
74 padding: 2px;
75 }
76 #total_row { font-weight: bold; }
77 .passClass { background-color: #6c6; }
78 .failClass { background-color: #c60; }
79 .errorClass { background-color: #c00; }
80 .passCase { color: #6c6; }
81 .failCase { color: #c60; font-weight: bold; }
82 .errorCase { color: #c00; font-weight: bold; }
83 .hiddenRow { display: none; }
84 .testcase { margin-left: 2em; }
85
86
87 /* -- ending ---------------------------------------------------------------------- */
88 #ending {
89 }
90
91 </style>
92
93 </head>
94 <body>
95 <script language="javascript" type="text/javascript"><!--
96 output_list = Array();
97
98 /* level - 0:Summary; 1:Failed; 2:All */
99 function showCase(level) {
100 trs = document.getElementsByTagName("tr");
101 for (var i = 0; i < trs.length; i++) {
102 tr = trs[i];
103 id = tr.id;
104 if (id.substr(0,2) == 'ft') {
105 if (level < 1) {
106 tr.className = 'hiddenRow';
107 }
108 else {
109 tr.className = '';
110 }
111 }
112 if (id.substr(0,2) == 'pt') {
113 if (level > 1) {
114 tr.className = '';
115 }
116 else {
117 tr.className = 'hiddenRow';
118 }
119 }
120 }
121 }
122
123
124 function showClassDetail(cid, count) {
125 var id_list = Array(count);
126 var toHide = 1;
127 for (var i = 0; i < count; i++) {
128 tid0 = 't' + cid.substr(1) + '.' + (i+1);
129 tid = 'f' + tid0;
130 tr = document.getElementById(tid);
131 if (!tr) {
132 tid = 'p' + tid0;
133 tr = document.getElementById(tid);
134 }
135 id_list[i] = tid;
136 if (tr.className) {
137 toHide = 0;
138 }
139 }
140 for (var i = 0; i < count; i++) {
141 tid = id_list[i];
142 if (toHide) {
143 document.getElementById('div_'+tid).style.display = 'none'
144 document.getElementById(tid).className = 'hiddenRow';
145 }
146 else {
147 document.getElementById(tid).className = '';
148 }
149 }
150 }
151
152
153 function showTestDetail(div_id){
154 var details_div = document.getElementById(div_id)
155 var displayState = details_div.style.display
156 // alert(displayState)
157 if (displayState != 'block' ) {
158 displayState = 'block'
159 details_div.style.display = 'block'
160 }
161 else {
162 details_div.style.display = 'none'
163 }
164 }
165
166
167 function html_escape(s) {
168 s = s.replace(/&/g,'&amp;');
169 s = s.replace(/</g,'&lt;');
170 s = s.replace(/>/g,'&gt;');
171 return s;
172 }
173
174 /* obsoleted by detail in <div>
175 function showOutput(id, name) {
176 var w = window.open("", //url
177 name,
178 "resizable,scrollbars,status,width=800,height=450");
179 d = w.document;
180 d.write("<pre>");
181 d.write(html_escape(output_list[id]));
182 d.write("\n");
183 d.write("<a href='javascript:window.close()'>close</a>\n");
184 d.write("</pre>\n");
185 d.close();
186 }
187 */
188 --></script>
189
190 <div class='heading'>
191 <h1>Unit Test Report</h1>
192 <p class='attribute'><strong>Start Time:</strong> 2018-01-08 18:05:31</p>
193 <p class='attribute'><strong>Duration:</strong> 0:00:02.208474</p>
194 <p class='attribute'><strong>Status:</strong> Pass 6</p>
195
196 <p class='description'></p>
197 </div>
198
199
200
201 <p id='show_detail_line'>Show
202 <a href='javascript:showCase(0)'>Summary</a>
203 <a href='javascript:showCase(1)'>Failed</a>
204 <a href='javascript:showCase(2)'>All</a>
205 </p>
206 <table id='result_table'>
207 <colgroup>
208 <col align='left' />
209 <col align='right' />
210 <col align='right' />
211 <col align='right' />
212 <col align='right' />
213 <col align='right' />
214 </colgroup>
215 <tr id='header_row'>
216 <td>Test Group/Test case</td>
217 <td>Count</td>
218 <td>Pass</td>
219 <td>Fail</td>
220 <td>Error</td>
221 <td>View</td>
222 </tr>
223
224 <tr class='passClass'>
225 <td>subject_sync.ClassNameVideo</td>
226 <td>2</td>
227 <td>2</td>
228 <td>0</td>
229 <td>0</td>
230 <td><a href="javascript:showClassDetail('c1',2)">Detail</a></td>
231 </tr>
232
233 <tr id='pt1.1' class='hiddenRow'>
234 <td class='none'><div class='testcase'>test_ClassNameVideo_noData</div></td>
235 <td colspan='5' align='center'>pass</td>
236 </tr>
237
238 <tr id='pt1.2' class='hiddenRow'>
239 <td class='none'><div class='testcase'>test_ClassNameVideo_success</div></td>
240 <td colspan='5' align='center'>pass</td>
241 </tr>
242
243 <tr class='passClass'>
244 <td>subject_sync.ConsolidationExercise</td>
245 <td>1</td>
246 <td>1</td>
247 <td>0</td>
248 <td>0</td>
249 <td><a href="javascript:showClassDetail('c2',1)">Detail</a></td>
250 </tr>
251
252 <tr id='pt2.1' class='hiddenRow'>
253 <td class='none'><div class='testcase'>test_ConsolidationExercise_success</div></td>
254 <td colspan='5' align='center'>pass</td>
255 </tr>
256
257 <tr class='passClass'>
258 <td>subject_sync.PointVideo</td>
259 <td>2</td>
260 <td>2</td>
261 <td>0</td>
262 <td>0</td>
263 <td><a href="javascript:showClassDetail('c3',2)">Detail</a></td>
264 </tr>
265
266 <tr id='pt3.1' class='hiddenRow'>
267 <td class='none'><div class='testcase'>test_PointVideo_noData</div></td>
268 <td colspan='5' align='center'>pass</td>
269 </tr>
270
271 <tr id='pt3.2' class='hiddenRow'>
272 <td class='none'><div class='testcase'>test_PointVideo_success</div></td>
273 <td colspan='5' align='center'>pass</td>
274 </tr>
275
276 <tr class='passClass'>
277 <td>subject_sync.SubjectTest</td>
278 <td>1</td>
279 <td>1</td>
280 <td>0</td>
281 <td>0</td>
282 <td><a href="javascript:showClassDetail('c4',1)">Detail</a></td>
283 </tr>
284
285 <tr id='pt4.1' class='hiddenRow'>
286 <td class='none'><div class='testcase'>test_SubjectTest_success</div></td>
287 <td colspan='5' align='center'>pass</td>
288 </tr>
289
290 <tr id='total_row'>
291 <td>Total</td>
292 <td>6</td>
293 <td>6</td>
294 <td>0</td>
295 <td>0</td>
296 <td>&nbsp;</td>
297 </tr>
298 </table>
299
300 <div id='ending'>&nbsp;</div>
301
302 </body>
303 </html>
304
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5 import HTMLTestRunner
6 from test_cases import sub_account
7
8 from test_suites import test_elecCard
9 from test_cases import register
10 from test_cases import personal_info
11 from test_cases import parent_space
12 from test_cases import app_record_statistic
13 from test_cases import subject_sync
14
15 start_dir = './test_cases'
16 suite_run = unittest.TestSuite()
17 suite_run = unittest.defaultTestLoader.discover(start_dir=start_dir, pattern='subject_sync.py')
18
19
20 #suite_run.addTest(app_record_statistic.AppRecordEveryday('test_getAppRecordEveryday_success'))
21
22 #suite_run.addTest(app_record_statistic.AppRecordReset('test_AppRecordReset_success'))
23 #suite_run.addTest(parent_space.ParentSpaceNewPassword('test_ParentSpaceNewPassword_success'))
24 #suite_run.addTest(parent_space.ParentSpaceNewPassword('test_ParentSpaceNewPassword_authCodeError'))
25 runner = HTMLTestRunner.HTMLTestRunner(outputdir='report')
26
27 if __name__ == '__main__':
28
29 runner.run(suite_run)
30
31
32
No preview for this file type

216 KB

216 KB

test_cases/__pycache__/app_record_statistic.cpython-36.pyc
No preview for this file type
test_cases/__pycache__/debugggggg.cpython-36.pyc
No preview for this file type
test_cases/__pycache__/eleccard_check.cpython-36.pyc
No preview for this file type
test_cases/__pycache__/eleccard_setUp.cpython-36.pyc
No preview for this file type
test_cases/__pycache__/parent_space.cpython-36.pyc
No preview for this file type
test_cases/__pycache__/personal_info.cpython-36.pyc
No preview for this file type
test_cases/__pycache__/press.cpython-36.pyc
No preview for this file type
test_cases/__pycache__/region_grade_school.cpython-36.pyc
No preview for this file type
test_cases/__pycache__/register.cpython-36.pyc
No preview for this file type
test_cases/__pycache__/sub_account.cpython-36.pyc
No preview for this file type
test_cases/__pycache__/subject_sync.cpython-36.pyc
No preview for this file type
test_cases/app_record_statistic.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5 import requests
6 from data_fixture.config_data import HOST_BOSS, HOST_STA
7 from data_fixture import create_testdata as CreateTestData
8 from data_fixture import config_data as Data
9 from data_fixture.mysql_db import DB
10 import time
11 from datetime import date
12
13 db_test = DB()
14
15
16 #提交app使用记录
17 class AppRecordSave(unittest.TestCase):
18 def setUp(self):
19 self.base_url = HOST_STA + '/app/record/save'
20
21 def tearDown(self):
22 print(self.result)
23
24 def test_AppRecordSave_success(self):
25 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
26 postData = {'appName': '学科同步',
27 'appPid': 'com.hjx.synsubject',
28 'timeSpent': 1088,
29 'userId': Data.USER_ID,
30 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND}
31 send_time = str(time.time()).split('.')[0]
32 r = requests.post(self.base_url, headers=headers, data=postData)
33 self.result = r.json()
34 self.assertEqual(self.result['status'], 1, 'test_AppRecordSave_success Error')
35 where = {'app_name': '学科同步',
36 'app_pid': 'com.hjx.synsubject',
37 'time_spent': 1088,
38 'user_id': Data.USER_ID,
39 'device_number': Data.DEVICE_NUMBER_CUS_BIND}
40 where_2 = " time_end >= {} ".format(send_time)
41 self.assertTrue(db_test.select_('analytics.app_record', where, where_2) >= 1, 'test_AppRecordSave_success data Error')
42
43
44 # 按时间段获取app使用统计
45 class AppRecordStats(unittest.TestCase):
46 def setUp(self):
47 self.base_url = HOST_STA + '/app/record/stats'
48 now = int(str(time.time()).split('.')[0])
49 CreateTestData.create_app_use_record(now, Data.USER_ID, Data.DEVICE_NUMBER_CUS_BIND)
50
51 def tearDown(self):
52 pass
53
54 def test_getAppRecordStats_all_success(self):
55 getData = {'userId': Data.USER_ID,
56 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
57 'type': 'all'}
58 r = requests.get(self.base_url, params=getData)
59 self.result_1 = r.json()
60 self.assertEqual(self.result_1['status'], 1, 'test_getAppRecordStats_all_success Error')
61 self.assertTrue(self.result_1['data']['gameTime'] > 0)
62 self.assertTrue(self.result_1['data']['studyTime'] > 0)
63
64 def test_getAppRecordStats_year_success(self):
65 getData = {'userId': Data.USER_ID,
66 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
67 'type': 'year'}
68 r = requests.get(self.base_url, params=getData)
69 self.result_2 = r.json()
70 self.assertEqual(self.result_2['status'], 1, 'test_getAppRecordStats_year_success Error')
71 self.assertTrue(self.result_2['data']['gameTime'] > 0)
72 self.assertTrue(self.result_2['data']['studyTime'] > 0)
73
74 def test_getAppRecordStats_month_success(self):
75 getData = {'userId': Data.USER_ID,
76 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
77 'type': 'month'}
78 r = requests.get(self.base_url, params=getData)
79 self.result_3 = r.json()
80 self.assertEqual(self.result_3['status'], 1, 'test_getAppRecordStats_month_success Error')
81 self.assertTrue(self.result_3['data']['gameTime'] > 0)
82 self.assertTrue(self.result_3['data']['studyTime'] > 0)
83
84 def test_getAppRecordStats_week_success(self):
85 getData = {'userId': Data.USER_ID,
86 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
87 'type': 'week'}
88 r = requests.get(self.base_url, params=getData)
89 self.result_4 = r.json()
90 self.assertEqual(self.result_4['status'], 1, 'test_getAppRecordStats_week_success Error')
91 self.assertTrue(self.result_4['data']['gameTime'] > 0)
92 self.assertTrue(self.result_4['data']['studyTime'] > 0)
93
94
95 # 获取应用统计top排名
96 class AppRecordTop(unittest.TestCase):
97 def setUp(self):
98 self.base_url = HOST_STA + '/app/record/top'
99 now = int(str(time.time()).split('.')[0])
100 CreateTestData.create_app_use_record(now, Data.USER_ID, Data.DEVICE_NUMBER_CUS_BIND)
101
102 def tearDown(self):
103 pass
104
105 def test_getAppRecordTop_hjx(self):
106 getData = {'userId': Data.USER_ID,
107 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
108 'type': 'hjx'}
109 r = requests.get(self.base_url, params=getData)
110 self.result_1 = r.json()
111 self.assertEqual(self.result_1['status'], 1, 'test_getAppRecordTop_hjx Error')
112 self.assertTrue(len(self.result_1['data']) > 0)
113
114 def test_getAppRecordTop_other(self):
115 getData = {'userId': Data.USER_ID,
116 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
117 'type': 'other'}
118 r = requests.get(self.base_url, params=getData)
119 self.result_2 = r.json()
120 self.assertEqual(self.result_2['status'], 1, 'test_getAppRecordTop_other Error')
121 self.assertTrue(len(self.result_2['data']) > 0)
122
123
124 # 获取某一天的app统计
125 class AppRecordOneday(unittest.TestCase):
126 def setUp(self):
127 self.base_url = HOST_STA + '/app/record/oneday'
128 self.now = int(str(time.time()).split('.')[0])
129 CreateTestData.create_app_use_record(self.now, Data.USER_ID, Data.DEVICE_NUMBER_CUS_BIND)
130
131 def tearDown(self):
132 pass
133
134 def test_getAppRecordOneday_success(self):
135 getData = {'userId': Data.USER_ID,
136 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
137 'dayTimestamp': str(time.mktime(date.today().timetuple())).split('.')[0]}
138 pageNum = 1
139 appRecord = []
140 while True:
141 getData.update({'pageNum':pageNum})
142 r = requests.get(self.base_url, params=getData)
143 self.result = r.json()
144 appRecord = appRecord + self.result['data']
145 if len(self.result['data']) == 0:
146 break
147 pageNum += 1
148
149 self.result_1 = r.json()
150 self.assertTrue(len(appRecord) == 24)
151
152 app_name = appRecord[0]['appName']
153 time_spent = appRecord[0]['timeSpentTotal']
154 time_end = appRecord[0]['latestTimeEnd']
155 source_id = appRecord[0]['sourceId']
156 category_id = appRecord[0]['categoryId']
157 categoryType = appRecord[0]['categoryType']
158 study_category = [25,26,27,28,57]
159 game_category = [37,38,39,100]
160
161 where_1 = {'app_name':app_name,
162 'time_spent':time_spent,
163 'time_end': time_end,
164 'source_id':source_id,
165 'category_id':category_id,
166 'user_id': Data.USER_ID,
167 'device_number': Data.DEVICE_NUMBER_CUS_BIND
168 }
169 self.assertEqual(db_test.select_('analytics.app_record', where_1) , 1)
170 if category_id in study_category:
171 self.assertEqual(categoryType, 1)
172 if category_id in game_category:
173 self.assertEqual(categoryType, 2)
174
175
176 # 获取几天的app统计
177 class AppRecordEveryday(unittest.TestCase):
178 def setUp(self):
179 self.base_url = HOST_STA + '/app/record/everyday'
180 self.now = int(str(time.time()).split('.')[0])
181 # CreateTestData.create_app_use_record(self.now, Data.USER_ID, Data.DEVICE_NUMBER_CUS_BIND)
182 CreateTestData.create_app_use_record(self.now, '7000000054686780', '123456789002')
183
184
185 def tearDown(self):
186 pass
187
188 def test_getAppRecordEveryday_success(self):
189 # getData = {'userId': Data.USER_ID,
190 # 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
191 # 'pageNum': 1,
192 # 'pageSize': 7}
193 getData = {'userId': '7000000054686780',
194 'deviceNumber': '123456789002',
195 'pageNum': 1,
196 'pageSize': 7}
197 r = requests.get(self.base_url, params=getData)
198 self.result = r.json()
199 self.assertEqual(self.result['status'], 1, 'test_getAppRecordEveryday_success Error')
200 self.assertEqual(self.result['data'][0]['gameTimeSpent'], 2550)
201 self.assertEqual(self.result['data'][0]['studyTimeSpent'], 3150)
202
203
204 # 获取当天的app统计
205 class AppRecordToday(unittest.TestCase):
206 def setUp(self):
207 self.base_url = HOST_STA + '/app/record/today'
208 self.now = int(str(time.time()).split('.')[0])
209 CreateTestData.create_app_use_record(self.now, Data.USER_ID, Data.DEVICE_NUMBER_CUS_BIND)
210
211 def tearDown(self):
212 pass
213
214 def test_AppRecordToday_success(self):
215 getData = {'userId': Data.USER_ID,
216 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND}
217 r = requests.get(self.base_url, params=getData)
218 self.result = r.json()
219 self.assertEqual(self.result['status'], 1, 'AppRecordToday Error')
220 self.assertEqual(self.result['data']['gameTimeSpent'], 2550)
221 self.assertEqual(self.result['data']['studyTimeSpent'], 3150)
222
223
224 #重置数据接口
225 class AppRecordReset(unittest.TestCase):
226 def setUp(self):
227 self.base_url = HOST_STA + '/app/record/reset'
228 # create elec card , to get mobile phpne
229 self.password = CreateTestData.get_parentSpace_password(Data.DEVICE_NUMBER_CUS_BIND)
230 now = int(str(time.time()).split('.')[0])
231 CreateTestData.create_app_use_record(now, Data.USER_ID, Data.DEVICE_NUMBER_CUS_BIND)
232
233 def tearDown(self):
234 pass
235
236 def test_AppRecordReset_success(self):
237 getData = {'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
238 'password': self.password,
239 'userId': Data.USER_ID
240 }
241 r = requests.post(self.base_url, data=getData)
242 self.result = r.json()
243 self.assertEqual(self.result['status'], 1, 'test_AppRecordReset_success Error')
244 where = {'device_number': Data.DEVICE_NUMBER_CUS_BIND,
245 'user_id': Data.USER_ID
246 }
247 self.assertEqual(db_test.select_('analytics.app_record', where), 0)
248
249 def test_AppRecordReset_passwordError(self):
250 getData = {'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
251 'userId': Data.USER_ID,
252 'password': self.password + '111'
253 }
254 r = requests.post(self.base_url, data=getData)
255 self.result_2 = r.json()
256 self.assertEqual(self.result_2['status'], 1005, 'test_AppRecordReset_passwordError Error')
257
258
259
260
test_cases/debugggggg.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import uuid
5
6 def create_app_use_record(user_id, device_number):
7
8 study_apps = [{'app_name':"百度英语资料大全", 'app_pid':'com.sailang.EnglishBook','category_id':'25', \
9 'source_id':'1','time_spent': 100, 'user_id': user_id, 'device_number': device_number},
10 {'app_name': '开心大学士', 'app_pid': 'com.ksense.study','category_id':'26', 'source_id':'1', \
11 'time_spent': 200, },
12 {'app_name': '驾考宝典', 'app_pid': 'com.handsgo.jiakao.android' ,'category_id':'27', 'source_id':'1', \
13 'time_spent': 300 },
14 {'app_name': '我爱汉字', 'app_pid': 'com.cronlygames.hanzi' ,'category_id':'28', 'source_id':'1',\
15 'time_spent': 400},
16 {'app_name': '拖拖乐3', 'app_pid': 'cn.com.wiisoft.tuotuo' ,'category_id':'57', 'source_id':'1', \
17 'time_spent': 100}]
18
19 for j in range(0,2):
20 for i in range(0, 2):
21 time_end_1 = {'time_end': 28800 + i * 1000, 'id':str(uuid.uuid4()).replace('-', '')}
22 study_app = study_apps[i]
23 study_app.update(time_end_1)
24 mm = study_app
25 ll = len(study_app['app_name'])
26 ss = study_app['app_name']
27
28
29 ################################################
30
31 def create_app_use_record_2(user_id, device_number):
32 study_apps = [{'app_name':'百度英语资料大全', 'app_pid':'com.sailang.EnglishBook','category_id':'25', 'source_id':'1', \
33 'time_spent': 100, 'user_id': user_id, 'device_number': device_number}
34 # {'app_name': '开心大学士', 'app_pid': 'com.ksense.study','category_id':'26', 'source_id':'1', \
35 # 'time_spent': 200, 'user_id': user_id, 'device_number': device_number},
36 # {'app_name': '驾考宝典', 'app_pid': 'com.handsgo.jiakao.android' ,'category_id':'27', 'source_id':'1', \
37 # 'time_spent': 300, 'user_id': user_id, 'device_number': device_number},
38 # {'app_name': '我爱汉字', 'app_pid': 'com.cronlygames.hanzi' ,'category_id':'28', 'source_id':'1',\
39 # 'time_spent': 400, 'user_id': user_id, 'device_number': device_number},
40 # {'app_name': '拖拖乐3', 'app_pid': 'cn.com.wiisoft.tuotuo' ,'category_id':'57', 'source_id':'1', \
41 # 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
42 # {'app_name': '幼儿数字算数学习', 'app_pid': 'com.syhrobert1991.infantlearning' ,'category_id':'25', \
43 # 'source_id':'1', 'time_spent': 200, 'user_id': user_id, 'device_number': device_number},
44 # {'app_name': '轻松背单词之初中英语', 'app_pid': 'petpestzx.wordroid.model' ,'category_id':'26', \
45 # 'source_id':'2', 'time_spent': 300, 'user_id': user_id, 'device_number': device_number},
46 # {'app_name': '有谱-爱学习(数理化)', 'app_pid': 'com.emingren.youpu' ,'category_id':'27', 'source_id':'2', \
47 # 'time_spent': 400, 'user_id': user_id, 'device_number': device_number},
48 # {'app_name': '疯狂音标', 'app_pid': 'com.neo.crazyphonetic' ,'category_id':'28', 'source_id':'2', \
49 # 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
50 # {'app_name': '互动作业V3.18.6', 'app_pid': 'com.v.study' ,'category_id':'57', 'source_id':'2', \
51 # 'time_spent': 250, 'user_id': user_id, 'device_number': device_number},
52 # {'app_name': '发音背单词', 'app_pid': 'org.liberty.android.fantastischmemo' ,'category_id':'57', \
53 # 'source_id':'2', 'time_spent': 350, 'user_id': user_id, 'device_number': device_number},
54 # {'app_name': '语文100', 'app_pid': 'com.kk.kkyuwen' ,'category_id':'57', 'source_id':'2', \
55 # 'time_spent': 450, 'user_id': user_id, 'device_number': device_number}
56 ]
57
58 game_apps = [{'app_name': '小伴龙新', 'app_pid': 'com.xiaobanlong.main' ,'category_id':'37', 'source_id':'1',\
59 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
60 {'app_name': '三国群英传', 'app_pid': 'com.tencent.tmgp.sgqyz' ,'category_id':'38', 'source_id':'1', \
61 'time_spent': 200, 'user_id': user_id, 'device_number': device_number},
62 {'app_name': '童言童语', 'app_pid': 'com.lingshi.kids' ,'category_id':'39', 'source_id':'2', \
63 'time_spent': 300, 'user_id': user_id, 'device_number': device_number},
64 {'app_name': '从前啊', 'app_pid': 'com.mojie.longlongago' ,'category_id':'37', 'source_id':'2', \
65 'time_spent': 400, 'user_id': user_id, 'device_number': device_number},
66 {'app_name': '永恒纪元', 'app_pid': 'com.m37.dtszj.uc' ,'category_id':'38', 'source_id':'2', \
67 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
68 {'app_name': '我的世界新', 'app_pid': 'com.netease.mc.aligames' ,'category_id':'39', 'source_id':'2', \
69 'time_spent': 200, 'user_id': user_id, 'device_number': device_number},
70 {'app_name': '球球大作战', 'app_pid': 'com.ztgame.bob', 'category_id': '37', 'source_id': '2', \
71 'time_spent': 300, 'user_id': user_id, 'device_number': device_number},
72 {'app_name': '葫芦侠我的世界', 'app_pid': 'com.huluxia.mctool', 'category_id': '38', 'source_id': '2',\
73 'time_spent': 400, 'user_id': user_id, 'device_number': device_number},
74 {'app_name': 'QQ游戏V6.8.7', 'app_pid': 'com.tencent.qqgame', 'category_id': '39', 'source_id': '2',\
75 'time_spent': 100, 'user_id': user_id, 'device_number': device_number},
76 {'app_name': '99围棋最新', 'app_pid': 'com.r99weiqi.dvd', 'category_id': '37', 'source_id': '2', \
77 'time_spent': 50, 'user_id': user_id, 'device_number': device_number},
78 {'app_name': '凯蒂环球之旅', 'app_pid': 'com.tencent.HelloKitty', 'category_id': '37', 'source_id': '2',\
79 'time_spent': 150, 'user_id': user_id, 'device_number': device_number},
80 {'app_name': '贪吃蛇大作战', 'app_pid': 'com.wepie.snake.qihoo', 'category_id': '100', 'source_id': '2',\
81 'time_spent': 250, 'user_id': user_id, 'device_number': device_number}
82 ]
83
84 # get date of the last 7 days(include today)
85 days = ['111111','222222','333333'] # the day should insert app records
86
87 for day in days:
88 for i in range(0, 12):
89 time_end_1 = {'time_end': int(day) + 28800 + i * 1000, 'id':str(uuid.uuid4()).replace('-', '')}
90 time_end_2 = {'time_end': int(day) + 29800 + i * 500, 'id':str(uuid.uuid4()).replace('-', '')}
91 #study_apps[i].update(time_end_1)
92 #game_apps[i].update(time_end_2)
93 study_app = study_apps[0]
94 study_app.update(time_end_1)
95 ll = len(study_app['app_name'])
96 ss = study_app['app_name']
97 game_app = game_apps[i]
98 game_app.update(time_end_2)
99 #db.insert('analytics.app_record_copy', study_app)
100 # db.insert('analytics.app_record_copy', game_app)
101
102
103 if __name__ == '__main__':
104 create_app_use_record_2('556600', 'HJKKJ1223123')
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
test_cases/eleccard_check.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import logging
5 import unittest
6 import requests
7 from data_fixture.config_data import HOST_BOSS
8 from data_fixture import create_testdata as CreateTestData
9 from data_fixture import config_data as Data
10
11
12 #检查是否需要绑定保卡
13 class CheckElecCardBind(unittest.TestCase):
14 def setUp(self):
15 self.base_url = HOST_BOSS + "/electronicCard/check"
16 CreateTestData.pre_elecCard(Data.DEVICE_NUMBER_CUS_BIND, Data.DEVICE_NUMBER_SAM, Data.DEVICE_NUMBER_CUS_UNBIND)
17
18 def tearDown(self):
19 print(self.result)
20
21 # 已绑定 -- 客机
22 def test_checkElecCard_customerMachine(self):
23 headers = {'Accept': '*/*'}
24 getData = {'deviceNumber':Data.DEVICE_NUMBER_CUS_BIND}
25 r = requests.get(self.base_url, headers=headers, params=getData)
26 self.result = r.json()
27 self.assertEqual(self.result['status'], 1, 'checkElecCard_customerMachine Error')
28
29 # 样机
30 def test_checkElecCard_sampleMachine(self):
31 headers = {'Accept': '*/*'}
32 getData = {'deviceNumber': Data.DEVICE_NUMBER_SAM}
33 r = requests.get(self.base_url, headers=headers, params=getData)
34 self.result = r.json()
35 self.assertEqual(self.result['status'], 2002, 'checkElecCard_sampleMachine Error')
36
37 # 未绑定 -- 客机
38 def test_checkElecCard_unbind(self):
39 headers = {'Accept': '*/*'}
40 getData = {'deviceNumber': Data.DEVICE_NUMBER_CUS_UNBIND}
41 r = requests.get(self.base_url, headers=headers, params=getData)
42 self.result = r.json()
43 self.assertEqual(self.result['status'], 2001, 'checkElecCard_unbind Error')
44
45
46 #获取保卡信息
47 class GetCardInfo(unittest.TestCase):
48 def setUp(self):
49 self.base_url = HOST_BOSS + "/electronicCard/info"
50 CreateTestData.pre_elecCard(Data.DEVICE_NUMBER_CUS_BIND)
51
52 def tearDown(self):
53 print(self.result)
54
55 def test_getCardInfo_success(self):
56 headers = {'Accept': '*/*'}
57 getData = {'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND}
58 r = requests.get(self.base_url, headers=headers, params=getData)
59 self.result = r.json()
60 self.assertEqual(self.result['status'], 1, 'getCardInfo Error')
61
test_cases/eleccard_setUp.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5 import requests
6 from data_fixture.config_data import HOST_BOSS, HOST_ADMIN
7 from data_fixture import create_testdata as CreateTestData
8 from data_fixture import config_data as Data
9
10
11 #添加客机保卡
12 class SetUpElecCard(unittest.TestCase):
13 def setUp(self):
14 self.base_url = HOST_BOSS + "/electronicCard/addCustomer"
15 CreateTestData.pre_SetUpElecCard()
16 def tearDown(self):
17 print(self.result)
18
19 def test_addElecCard_success(self):
20 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
21 postData = {'userId':Data.USER_ID,
22 'customerName':'customer测试',
23 'customerAddress':'田林路487号',
24 'buyAddress':'虹梅路888号',
25 'buyTime':'2017-12-02',
26 'alterSaleCall':'55558888',
27 'productModel':'TEST',
28 'deviceNumber': Data.DEVICE_NUMBER_NEW,
29 'macAddress':Data.MAC_NEW,
30 'customerPhone':Data.USER_PHONE
31 }
32 r = requests.post(self.base_url, headers=headers, data=postData)
33 self.result = r.json()
34 self.assertEqual(self.result['status'], 1, 'addElecCard Error')
35
36
37 # 置为样机,提交终端信息
38 class SetToSample(unittest.TestCase):
39
40 def setUp(self):
41 self.base_url = HOST_ADMIN + "/admin/elecCard/updateToSample"
42 CreateTestData.pre_elecCard(device_cus_bind=Data.DEVICE_NUMBER_TO_SAM)
43
44 def tearDown(self):
45 pass
46
47 def test_updateToSample_success(self):
48 headers = {'Content-Type': 'multipart/form-data', 'Accept': 'application/json'}
49 postData = {'userId':Data.USER_ID,
50 'deviceNumber':Data.DEVICE_NUMBER_TO_SAM,
51 'terminalAddress':'terminalAddress终端地址',
52 'distributor':'distributor经销商',
53 'saleClerk':'saleClerk销售员',
54 'mobilePhone':'18944444444'
55 }
56 files = {'photo':('252ED989-0B16-4AB7-81C1-974ABCF6CA11.png','image/png')}
57 r = requests.post(self.base_url, headers=headers, files=files, data=postData, allow_redirects=False)
58 self.assertEqual(r.status_code, 302, 'updateToSampleError')
59
60
61 #置为客机
62 class SetToCustomer(unittest.TestCase):
63
64 def setUp(self):
65 self.base_url = HOST_ADMIN + "/admin/elecCard/updateToCustomer"
66 CreateTestData.pre_elecCard(device_sam=Data.DEVICE_NUMBER_TO_CUS)
67
68 def tearDown(self):
69 pass
70
71 def test_updateToCustomer_success(self):
72 headers = {'Accept': 'application/json'}
73 getData = {'userId': Data.USER_ID, 'deviceNumber': Data.DEVICE_NUMBER_TO_CUS}
74 r = requests.get(self.base_url, data=getData, allow_redirects=False)
75 self.assertEqual(r.status_code, 302, 'updateToCustomerError')
76
77
78 #解绑保卡
79 class Unbind(unittest.TestCase):
80 def setUp(self):
81 self.base_url = HOST_ADMIN + "/admin/elecCard/delete"
82 CreateTestData.pre_elecCard(device_cus_bind=Data.DEVICE_NUMBER_UNBIND)
83
84 def tearDown(self):
85 pass
86
87 def test_unbindCard_success(self):
88 headers = {'Accept': '*/*'}
89 getData = {'deviceNumber': Data.DEVICE_NUMBER_UNBIND}
90 r = requests.get(self.base_url, headers=headers, data=getData, allow_redirects=False)
91 # self.result = r.json()
92 self.assertEqual(r.status_code, 302, 'unbindCardError')
93
94
95 #修改保卡
96 class Card_Modify(unittest.TestCase):
97 def setUp(self):
98 self.base_url = HOST_BOSS + "/electronicCard/updateByUserId"
99 CreateTestData.pre_elecCard(device_cus_bind=Data.DEVICE_NUMBER_EDIT)
100 self.authCode = CreateTestData.fet_authCode(Data.USER_PHONE_EDIT)
101
102 def tearDown(self):
103 print(self.result)
104
105 def test_modifyCardInfo_phone_success(self):
106 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
107 postData = {
108 'customerPhone':Data.USER_PHONE_EDIT,
109 'authCode':self.authCode,
110 'deviceNumber': Data.DEVICE_NUMBER_EDIT
111 }
112 r = requests.post(self.base_url, headers=headers, data=postData)
113 self.result = r.json()
114 self.assertEqual(self.result['status'], 1, 'elecCardModifyError')
115
116 def test_modifyCardInfo_address_success(self):
117 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
118 postData = {
119 'deviceNumber': Data.DEVICE_NUMBER_EDIT,
120 'customerAddress': '上海徐汇区田林路888号修改',
121 'customerPhone': Data.USER_PHONE_EDIT,
122 'authCode':self.authCode
123 }
124 r = requests.post(self.base_url, headers=headers, data=postData)
125 self.result = r.json()
126 self.assertEqual(self.result['status'], 1, 'elecCardModifyError')
127
128
129
test_cases/parent_space.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5 import requests
6 from data_fixture.config_data import HOST_BOSS, HOST_STA
7 from data_fixture import create_testdata as CreateTestData
8 from data_fixture import config_data as Data
9 from data_fixture.mysql_db import DB
10 import uuid
11 import time
12
13
14 db_test = DB()
15
16 # 家长控制登录
17 class ParentSpaceLogin(unittest.TestCase):
18 def setUp(self):
19 self.base_url = HOST_BOSS + '/parentsSpacePass/login'
20 self.password = CreateTestData.get_parentSpace_password(Data.DEVICE_NUMBER_CUS_BIND)
21
22 def tearDown(self):
23 print(self.result)
24
25 def test_ParentSpaceLogin_success(self):
26 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
27 postData = {'password': self.password,
28 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND
29 }
30 r = requests.post(self.base_url, headers=headers, data=postData)
31 self.result = r.json()
32 self.assertEqual(self.result['status'], 1, 'ParentSpaceLogin Error')
33
34 def test_ParentSpaceLogin_WrongPassword(self):
35 password_wrong = self.password + '11'
36 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
37 postData = {'password': password_wrong,
38 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND
39 }
40 r = requests.post(self.base_url, headers=headers, data=postData)
41 self.result = r.json()
42 self.assertEqual(self.result['status'], 1005, 'test_ParentSpaceLogin_WrongPassword Error')
43
44
45 # 家长控制修改密码
46 class ParentSpaceChangePassword(unittest.TestCase):
47 def setUp(self):
48 self.base_url = HOST_BOSS + '/parentsSpacePass/changePassword'
49 self.oldPass = CreateTestData.get_parentSpace_password(Data.DEVICE_NUMBER_CUS_BIND)
50
51 def tearDown(self):
52 print(self.result)
53
54 def test_ParentSpaceChangePassword_success(self):
55 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
56 postData = {'oldPass': self.oldPass,
57 'newPass': '111111',
58 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND
59 }
60 r = requests.post(self.base_url, headers=headers, data=postData)
61 self.result = r.json()
62 self.assertEqual(self.result['status'], 1, 'ParentSpacehangePassword Error')
63 where = {'password': '111111',
64 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND }
65 self.assertEqual(db_test.select_('acornuser.parents_space_pass', where), 1, 'ParentSpacehangePassword data Error')
66
67
68 #家长控制忘记密码
69 class ParentSpaceNewPassword(unittest.TestCase):
70 def setUp(self):
71 self.base_url = HOST_BOSS + '/parentsSpacePass/newpassword'
72 CreateTestData.pre_elecCard(Data.DEVICE_NUMBER_CUS_BIND)
73 sql = "SELECT customerPhone FROM acornuser.ozing_customermachine where deviceNumber = '{}'".format(Data.DEVICE_NUMBER_CUS_BIND)
74 self.mobile = db_test.select(sql)[0]["customerPhone"].strip()
75 self.auth = CreateTestData.fet_authCode(self.mobile)
76
77 def tearDown(self):
78 pass
79
80 def test_ParentSpaceNewPassword_success(self):
81 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
82 postData = {'userName': self.mobile,
83 'authCode': self.auth,
84 'password': '111111',
85 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND
86 }
87 r = requests.post(self.base_url, headers=headers, data=postData)
88 self.result = r.json()
89 self.assertEqual(self.result['status'], 1, 'test_ParentSpaceNewPassword_success Error')
90 where = {'password': '111111',
91 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND }
92 self.assertEqual(db_test.select_('acornuser.parents_space_pass', where), 1, 'ParentSpacehangePassword data Error')
93
94 def test_ParentSpaceNewPassword_authCodeError(self):
95 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
96 postData = {'userName': self.mobile,
97 'authCode': str(int(self.auth) - 1),
98 'password': '111111',
99 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND
100 }
101 r = requests.post(self.base_url, headers=headers, data=postData)
102 self.result_2 = r.json()
103 self.assertEqual(self.result_2['status'], 1001, 'test_ParentSpaceNewPassword_success Error')
104
105
106
107
test_cases/personal_info.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5 import requests
6 from data_fixture.config_data import HOST_BOSS
7 from data_fixture import config_data as Data
8 from data_fixture import create_testdata
9 from data_fixture.mysql_db import DB
10 import os
11 import uuid
12
13 db_test = DB()
14 current_dir = str(os.path.dirname(__file__))
15
16 #获取个人信息
17 class GetPersonalInfo(unittest.TestCase):
18 def setUp(self):
19 self.base_url = HOST_BOSS + "/personal/get"
20 self.subAccount = str(uuid.uuid4()).replace('-', '')
21 create_testdata.pre_subAccount(Data.USER_ID, self.subAccount, 1)
22
23 def tearDown(self):
24 pass
25
26 def test_getParentAccountInfo_success(self):
27 headers = {'Accept': '*/*'}
28 getData = {'userId': Data.USER_ID, 'type': 1}
29 r = requests.get(self.base_url, headers=headers, params=getData)
30 self.result_1 = r.json()
31 self.assertEqual(self.result_1['status'], 1, 'get parent info fail')
32
33 def test_getChildAccountInfo_success(self):
34 headers = {'Accept': '*/*'}
35 getData = {'userId': Data.USER_ID, 'type': 2}
36 r = requests.get(self.base_url, headers=headers, params=getData)
37 self.result_2 = r.json()
38 self.assertEqual(self.result_2['status'], 1, 'get child info fail')
39
40
41 #修改个人信息
42 class UpdatePersonalInfo(unittest.TestCase):
43 def setUp(self):
44 self.base_url = HOST_BOSS + "/personal/update"
45 self.subAccount = str(uuid.uuid4()).replace('-', '')
46 create_testdata.pre_subAccount(Data.PARENT_ID, self.subAccount, 1)
47
48 def tearDown(self):
49 pass
50
51 def test_UpdateParentInfo_success(self):
52 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
53 postData = {
54 'userId':Data.PARENT_ID,
55 'type': 1,
56 'name':'主账户',
57 'birthday':'2003-12-12',
58 'gradeId': '9',
59 'regionId' : '320100',
60 'schoolId': '500018',
61 'qq': '1313131313',
62 'gender': 'female',
63 'regionName': '江苏南京玄武',
64 'deviceNumber': Data.DEVICE_NUMBER_NEW,
65 'address':'幸福小区308'
66 }
67 where_data_1 = {'id':Data.PARENT_ID, 'qq': '1313131313'}
68 where_data_2 = {'user_id':Data.PARENT_ID, 'school_id': '500018'}
69 where_data_3 = {'user_id':Data.PARENT_ID, 'address':'幸福小区308'}
70 r = requests.post(self.base_url, headers=headers, data=postData)
71 self.result_1 = r.json()
72 self.assertEqual(self.result_1['status'], 1, 'UpdateParentInfo ERROR')
73 self.assertTrue(db_test.select_('acornuser.acorn_user', where_data_1), 1)
74 self.assertTrue(db_test.select_('acornuser.ozing_student', where_data_2), 1)
75 self.assertTrue(db_test.select_('acornuser.acorn_user_extra', where_data_3), 1)
76
77
78 def test_UpdateChildInfo_success(self):
79 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
80 postData = {
81 'userId': Data.PARENT_ID,
82 'type': 2,
83 'name': '子账户',
84 'birthday': '2010-12-12',
85 'gradeId': '6',
86 'regionId': '330100',
87 'schoolId': '6129',
88 'qq': '1515151515',
89 'gender': 'female',
90 'regionName': '浙江杭州西湖',
91 'deviceNumber': Data.DEVICE_NUMBER_NEW,
92 'address': '鲜花小区808'
93 }
94 where_data_child = {'qq': '1515151515', 'address': '鲜花小区808'}
95 r = requests.post(self.base_url, headers=headers, data=postData)
96 self.result_2 = r.json()
97 self.assertEqual(self.result_2['status'], 1, 'UpdateParentInfo ERROR')
98 self.assertTrue(db_test.select_('acornuser.child_user', where_data_child))
99
100
101 # 添加和修改个性签名
102 class AddorUpdateSignature(unittest.TestCase):
103 def setUp(self):
104 self.base_url = HOST_BOSS + "/signature/addOrUpdateSignature"
105 self.subAccount = str(uuid.uuid4()).replace('-', '')
106 create_testdata.pre_subAccount(Data.PARENT_ID, self.subAccount, 0)
107 create_testdata.checkSignatureExists(Data.PARENT_ID, 1)
108 create_testdata.checkSignatureExists(self.subAccount, 2)
109
110 def tearDown(self):
111 pass
112
113 def test_AddParentSignature_success(self):
114 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
115 postData = {'userId':Data.PARENT_ID,
116 'signature':'who is the clever Polly 谁是聪明的鹦鹉',
117 'type': 1}
118 r = requests.post(self.base_url, headers=headers, data=postData)
119 self.result_1 = r.json()
120 self.assertEqual(self.result_1['status'], 1, 'AddParentSignature ERROR')
121 where_1 = {'user_id':Data.PARENT_ID,
122 'signature':'who is the clever Polly 谁是聪明的鹦鹉'}
123 self.assertEqual(db_test.select_('acornuser.acorn_user_extra', where_1), 1)
124
125 def test_UpdateParentSignature_success(self):
126 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
127 postData = {'userId':Data.PARENT_ID,
128 'signature':'clever Polly 一只吵人的鹦鹉',
129 'type': 1}
130 r = requests.post(self.base_url, headers=headers, data=postData)
131 self.result_2 = r.json()
132 self.assertEqual(self.result_2['status'], 1, 'UpdateParentSignature ERROR')
133 where_2 = {'user_id':Data.PARENT_ID,
134 'signature':'clever Polly 一只吵人的鹦鹉'}
135 self.assertEqual(db_test.select_('acornuser.acorn_user_extra', where_2), 1, 'UpdateParentSignature ERROR')
136
137 def test_AddChildSignature_success(self):
138 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
139 postData = {'userId':self.subAccount,
140 'signature':'Polly can you spell its name 波利',
141 'type': 2}
142 r = requests.post(self.base_url, headers=headers, data=postData)
143 self.result_3 = r.json()
144 self.assertEqual(self.result_3['status'], 1, 'AddChildSignature ERROR')
145 where_1 = {'sub_account_id':self.subAccount,
146 'signature':'Polly can you spell its name 波利'}
147 self.assertEqual(db_test.select_('acornuser.subAccount_user_extra', where_1), 1, 'AddChildSignature ERROR')
148
149 def test_UpdateChildSignature_success(self):
150 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
151 postData = {'userId':self.subAccount,
152 'signature':'波利 P-O-L-L-Y',
153 'type': 2}
154 r = requests.post(self.base_url, headers=headers, data=postData)
155 self.result_4 = r.json()
156 self.assertEqual(self.result_4['status'], 1, 'UPDATEChildSignature ERROR')
157 where_1 = {'sub_account_id':self.subAccount,
158 'signature':'波利 P-O-L-L-Y'}
159 self.assertEqual(db_test.select_('acornuser.subAccount_user_extra', where_1), 1, 'UPDATEChildSignature ERROR')
160
161
162 # 显示个性签名
163 class GetSignature(unittest.TestCase):
164 def setUp(self):
165 self.base_url = HOST_BOSS + "/signature/info"
166 self.subAccount = str(uuid.uuid4()).replace('-', '')
167 create_testdata.checkSignatureExists(Data.PARENT_ID, 1)
168 create_testdata.checkSignatureExists(self.subAccount, 2)
169
170 def tearDown(self):
171 pass
172
173 def test_getParentSignature_success(self):
174 headers = {'Accept': '*/*'}
175 getData = {'userId': Data.PARENT_ID, 'type': 1}
176 r = requests.get(self.base_url, headers=headers, params=getData)
177 self.result_1 = r.json()
178 self.assertEqual(self.result_1['status'], 1, 'get parent Signature fail')
179
180 def test_getChildSignature_success(self):
181 headers = {'Accept': '*/*'}
182 getData = {'userId': self.subAccount, 'type': 2}
183 r = requests.get(self.base_url, headers=headers, params=getData)
184 self.result_2 = r.json()
185 self.assertEqual(self.result_2['status'], 1, 'get child Signature fail')
186
187
188 #更新用户头像 -- 默认图片
189 class UpdatePortraitDefault(unittest.TestCase):
190 def setUp(self):
191 self.base_url = HOST_BOSS + "/profile/picture/default"
192 self.subAccount = str(uuid.uuid4()).replace('-', '')
193 create_testdata.pre_subAccount(Data.PARENT_ID, self.subAccount, 0)
194
195 def tearDown(self):
196 pass
197
198 def test_UpdateParentPortraitDefault_success(self):
199 headers = {'Accept': '*/*', 'Content-Type':'application/x-www-form-urlencoded'}
200 postData = {'userId': Data.PARENT_ID, 'type': 1,
201 'defaultImg':'http://hjxprodbucket.oss.aliyuncs.com/static/upload/boss_api/announcement/2017-08-29/61e8d8cf-651f-49c9-beb2-ff1387af390a.png'}
202 r = requests.post(self.base_url, headers=headers, data=postData)
203 self.result_1 = r.json()
204 self.assertEqual(self.result_1['status'], 1, 'UpdateParentPortrait fail')
205 where = {'user_id': Data.PARENT_ID,
206 'portrait':'static/upload/boss_api/announcement/2017-08-29/61e8d8cf-651f-49c9-beb2-ff1387af390a.png'}
207 self.assertEqual(db_test.select_('acornuser.ozing_student', where), 1, 'UpdateParentPortraitDefault fail')
208
209 def test_UpdateChildPortraitDefault_success(self):
210 headers = {'Accept': '*/*', 'Content-Type':'application/x-www-form-urlencoded'}
211 postData = {'userId': self.subAccount, 'type': 2,
212 'defaultImg': 'http://hjxprodbucket.oss.aliyuncs.com/static/upload/boss_api/announcement/2017-08-29/61e8d8cf-651f-49c9-beb2-ff1387af390a.png'}
213 r = requests.post(self.base_url, headers=headers, data=postData)
214 self.result_2 = r.json()
215 self.assertEqual(self.result_2['status'], 1, 'UpdateChildPortrait fail')
216 where = {'subAccountId': self.subAccount,
217 'image': 'static/upload/boss_api/announcement/2017-08-29/61e8d8cf-651f-49c9-beb2-ff1387af390a.png'}
218 self.assertEqual(db_test.select_('acornuser.child_user', where), 1, 'UpdateChildPortraitDefault fail')
219
220
221 #更新用户头像-- 上传文件
222 class UpdatePortrait(unittest.TestCase):
223 def setUp(self):
224 self.base_url = HOST_BOSS + "/profile/picture/update"
225 img_file_1 = current_dir + '/1.jpg'
226 img_file_2 = current_dir + '/1.png'
227 self.img_1 = open(img_file_1, 'rb')
228 self.img_2 = open(img_file_2, 'rb')
229 self.subAccount = str(uuid.uuid4()).replace('-', '')
230 create_testdata.pre_subAccount(Data.PARENT_ID, self.subAccount, 0)
231
232 def tearDown(self):
233 pass
234
235 def test_UpdateParentPortraitDefault_success(self):
236 headers = {'Accept': '*/*', 'Content-Type':'multipart/form-data; boundary=cada83b1d4b82a7ccd28ae8f7f6d6'}
237 postData = {'userId': Data.PARENT_ID, 'type': 1}
238 file = {'img': self.img_1}
239 r = requests.post(self.base_url, data=postData, files=file)
240 ss = r.request
241 self.img_1.close()
242 self.result_1 = r.json()
243 self.assertEqual(self.result_1['status'], 1, 'UpdateParentPortrait fail')
244 self.assertEqual(len(self.result_1['data']), 1, 'UpdateParentPortrait data fail')
245
246 def test_UpdateChildPortrait_success(self):
247 headers = {'Accept': '*/*', 'Content-Type':'multipart/form-data; boundary=fa0cada83b1d4b82a7ccd28ae8f7f6d6'}
248 postData = {'userId': self.subAccount, 'type': 2}
249 file = {'img': self.img_2}
250 r = requests.post(self.base_url, data=postData, files=file)
251 ss = r.request
252 self.img_2.close()
253 self.result_2 = r.json()
254 self.assertEqual(self.result_2['status'], 1, 'UpdateChildPortrait fail')
255 self.assertEqual(len(self.result_2['data']), 1, 'UpdateChildPortrait data fail')
256
257
258
test_cases/press.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5 import requests
6 from data_fixture.config_data import HOST_BOSS
7 from data_fixture import create_testdata as CreateTestData
8 from data_fixture import config_data as Data
9 from data_fixture.mysql_db import DB
10
11 db_test = DB()
12
13
14 # 获取教材版本列表
15 class GetPressList(unittest.TestCase):
16 def setUp(self):
17 self.base_url = HOST_BOSS + '/press/list'
18
19 def tearDown(self):
20 print(self.result)
21
22 def test_getPressList_success(self):
23 headers = {'Accept': '*/*'}
24 getData = {'subjectName': '数学'}
25 r = requests.get(self.base_url, headers=headers, params=getData)
26 self.result = r.json()
27 self.assertEqual(self.result['status'], 1, 'getPressList Error')
28 self.assertTrue(len(self.result['data']) > 1, 'getPressList data Error')
29
30
31 # 获取用户版本信息接口
32 class GetUserPressInfo(unittest.TestCase):
33 def setUp(self):
34 self.base_url = HOST_BOSS + '/userPress/info'
35 CreateTestData.pre_GetUserPressInfo(Data.USER_ID)
36
37 def tearDown(self):
38 print(self.result)
39
40 def test_getPressList_success(self):
41 headers = {'Accept': '*/*'}
42 getData = {'userId': Data.USER_ID, 'gradeId': 9}
43 r = requests.get(self.base_url, headers=headers, params=getData)
44 self.result = r.json()
45 self.assertEqual(self.result['status'], 1, 'GetUserPressInfo Error')
46 data = self.result['data']
47 for item in data:
48 if item['subject'] == '语文':
49 press_to_check = item['press']
50 self.assertEqual(press_to_check, '北京师范大学出版社', 'GetUserPressInfo data Error')
51
52
53 # 修改版本信息接口
54 class UpdateUserPressInfo(unittest.TestCase):
55 def setUp(self):
56 self.base_url = HOST_BOSS + '/userPress/update'
57
58 def tearDown(self):
59 print(self.result)
60
61 def test_getPressList_success(self):
62 headers = {'Accept': '*/*', 'Content-Type': 'application/x-www-form-urlencoded'}
63 postData = {'userId': Data.USER_ID,
64 'chemistry': '山东教育出版社',
65 'chinese': '江苏教育出版社',
66 'biology': '人民教育出版社',
67 'geography': '人民教育出版社',
68 'physics': '人民教育出版社',
69 'english': '外语教学与研究出版社',
70 'political': '人民教育出版社',
71 'math': '江苏科学技术出版社',
72 'history': '人民教育出版社'
73 }
74 r = requests.post(self.base_url, headers=headers, data=postData)
75 self.result = r.json()
76 self.assertEqual(self.result['status'], 1, 'UpdateUserPressInfo Error')
77 where = {'user_id': Data.USER_ID,
78 'chemistry': '山东教育出版社',
79 'chinese': '江苏教育出版社',
80 'biology': '人民教育出版社',
81 'geography': '人民教育出版社',
82 'physics': '人民教育出版社',
83 'english': '外语教学与研究出版社',
84 'political': '人民教育出版社',
85 'math': '江苏科学技术出版社',
86 'history': '人民教育出版社'
87 }
88 self.assertEqual(db_test.select_('acornuser.user_press', where), 1, 'UpdateUserPressInfo data Error')
89
90
91
92
test_cases/region_grade_school.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5 import requests
6 from data_fixture.config_data import HOST_BOSS
7
8 # 省
9 class GetProvince(unittest.TestCase):
10 def setUp(self):
11 self.base_url = HOST_BOSS + "/ozing/provinces"
12
13 def tearDown(self):
14 print(self.result)
15
16 def test_getProvince_success(self):
17 headers = {'Accept': '*/*'}
18 r = requests.get(self.base_url, headers=headers)
19 self.result = r.json()
20 self.assertEqual(self.result['status'], 100, 'get province fail')
21 self.assertTrue(len(self.result['provinces']) > 0, 'province data wrong')
22
23 # 市
24 class GetCities(unittest.TestCase):
25 def setUp(self):
26 self.base_url = HOST_BOSS + "/ozing/cities"
27 self.regionId = '330000' #浙江
28 self.city ='330100' # 杭州
29
30 def tearDown(self):
31 print(self.result)
32
33 def test_getCities_success(self):
34 headers = {'Accept': '*/*'}
35 getData = {'regionId': self.regionId}
36 r = requests.get(self.base_url, params=getData)
37 self.result = r.json()
38 self.assertEqual(self.result['status'], 100, 'get cities fail')
39 self.assertTrue(len(self.result['cities']) > 0, 'cities data wrong')
40
41 # 区
42 class GetCounties(unittest.TestCase):
43 def setUp(self):
44 self.base_url = HOST_BOSS + "/ozing/counties"
45 self.regionId = '330100' # 杭州
46 self.county ='330106' # 西湖
47
48 def tearDown(self):
49 print(self.result)
50
51 def test_getCounties_success(self):
52 headers = {'Accept': '*/*'}
53 getData = {'regionId': self.regionId}
54 r = requests.get(self.base_url, params=getData)
55 self.result = r.json()
56 self.assertEqual(self.result['status'], 100, 'get counties fail')
57 self.assertTrue(len(self.result['counties']) > 0, 'counties data wrong')
58
59 # 年级
60 class GetGrades(unittest.TestCase):
61 def setUp(self):
62 self.base_url = HOST_BOSS + "/grades"
63
64 def tearDown(self):
65 print(self.result)
66
67 def test_getGrades_success(self):
68 headers = {'Accept': 'application/json'}
69 r = requests.get(self.base_url, headers=headers)
70 self.result = r.json()
71 self.assertTrue(len(self.result['data']) > 0, 'grades data wrong')
72
73
74 # 学校
75 class GetSchools(unittest.TestCase):
76 def setUp(self):
77 self.base_url = HOST_BOSS + "/school/get"
78 self.regionId = '330106' #西湖
79 self.gradeId = '6' #五年级
80
81 def tearDown(self):
82 print(self.result)
83
84 def test_getSchools_success(self):
85 headers = {'Accept': 'application/json'}
86 getData = {'regionId': self.regionId, 'gradeId': self.gradeId}
87 r = requests.get(self.base_url, headers=headers, params=getData)
88 self.result = r.json()
89 self.assertTrue(len(self.result['data']) > 0, 'school data wrong')
90
test_cases/register.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5 import requests
6 from data_fixture.config_data import HOST_BOSS
7 from data_fixture import create_testdata as CreateTestData
8 from data_fixture import config_data as Data
9 from data_fixture.mysql_db import DB
10 import os
11 from requests_toolbelt import MultipartEncoder
12
13 db_test = DB()
14 current_dir = str(os.path.dirname(__file__))
15
16 #手机号重复验证
17 class PhoneUsedCheck(unittest.TestCase):
18 def setUp(self):
19 self.base_url = HOST_BOSS + "/ozing/timer/user/registered"
20 CreateTestData.pre_phoneUsedCheck(Data.USER_PHONE_USED, True)
21 CreateTestData.pre_phoneUsedCheck(Data.USER_PHONE_UNUSED, False)
22
23 def tearDown(self):
24 print(self.result)
25
26 # 注册过的手机号
27 def test_phone_used(self):
28 getData = {'mobile':Data.USER_PHONE_USED}
29 r = requests.get(self.base_url, params=getData)
30 self.result = r.json()
31 self.assertEqual(self.result['status'], True)
32
33 # 手机号未注册
34 def test_phone_unused(self):
35 getData = {'mobile':Data.USER_PHONE_UNUSED}
36 r = requests.get(self.base_url, params=getData)
37 self.result = r.json()
38 self.assertEqual(self.result['status'], False)
39
40
41 # 获取验证码 --register
42 class GetAuthCode(unittest.TestCase):
43 def setUp(self):
44 self.base_url = HOST_BOSS + "/ozing/timer/user/fetchAuthCode"
45 self.mobile = '13833333333'
46
47 def tearDown(self):
48 print(self.result)
49
50 def test_getAuthCode_success(self):
51 headers = {'Accept': '*/*'}
52 postData = {'mobile': self.mobile, 'type': 'register'}
53 r = requests.post(self.base_url, headers=headers, data=postData)
54 self.result = r.json()
55 self.assertEqual(self.result['status'], 100)
56
57
58 #用户注册
59 class SignIn(unittest.TestCase):
60 def setUp(self):
61 self.base_url = HOST_BOSS + "/ozing/timer/anking/user"
62 self.smsCode = CreateTestData.fet_authCode(Data.USER_PHONE)
63 CreateTestData.pre_phoneUsedCheck(Data.USER_PHONE, False)
64
65 def tearDown(self):
66 print(self.result)
67
68 def test_signIn_success(self):
69 headers = {'Content-Type': 'application/json', 'Accept': '*/*'}
70 postData = {
71 "username": Data.USER_PHONE,
72 "password": 'Hjx111111',
73 "source": 'Android',
74 "smscode": self.smsCode
75 }
76 r = requests.post(self.base_url, headers=headers, json=postData)
77 self.result = r.json()
78 self.assertEqual(self.result['status'], 100)
79
80
81 # 检查用户注册信息是否完整
82 class RegisterExtrainfoCheck(unittest.TestCase):
83 def setUp(self):
84 self.base_url = HOST_BOSS + '/register/extrainfo/check'
85 CreateTestData.pre_register_extrainfo_check(Data.USER_ID, True)
86 CreateTestData.pre_register_extrainfo_check(Data.USER_ID_INCOMPLETE, False)
87
88 def tearDown(self):
89 pass
90
91 def test_checkRegisterExtrainfo_Complete_success(self):
92 headers = {'Accept': '*/*'}
93 getData = {'userId': Data.USER_ID}
94 r = requests.get(self.base_url, headers=headers, params=getData)
95 self.result_1 = r.json()
96 self.assertEqual(self.result_1['status'], 1, 'test_checkRegisterExtrainfo_Complete fail')
97 self.assertEqual(self.result_1['data']['isRegisterInfoComplete'], True, 'test_checkRegisterExtrainfo_Complete data fail')
98
99 def test_checkRegisterExtrainfo_inComplete_success(self):
100 headers = {'Accept': '*/*'}
101 getData = {'userId': Data.USER_ID_INCOMPLETE}
102 r = requests.get(self.base_url, headers=headers, params=getData)
103 self.result_2 = r.json()
104 self.assertEqual(self.result_2['status'], 1, 'test_checkRegisterExtrainfo_inComplete fail')
105 self.assertEqual(self.result_2['data']['isRegisterInfoComplete'], False,
106 'test_checkRegisterExtrainfo_inComplete data fail')
107
108
109 # 提交注册信息
110 class RegisterExtrainfoSubmit(unittest.TestCase):
111 def setUp(self):
112 self.base_url = HOST_BOSS + '/register/extrainfo/submit'
113
114 def tearDown(self):
115 print(self.result)
116
117 def test_RegisterExtrainfoSubmit_success(self):
118 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
119 postData = {
120 'name': '测试测试lalalallal',
121 'gradeId': 7,
122 'schoolId': 68779,
123 'regionName': '浙江杭州西湖',
124 'regionId': 330106,
125 'userId': Data.USER_ID,
126 'chinese': '北京出版社',
127 'english': '人民教育出版社',
128 'math': '人民教育出版社'
129 }
130 r = requests.post(self.base_url, headers=headers, data=postData)
131 self.result = r.json()
132 self.assertEqual(self.result['status'], 1, 'RegisterExtrainfoSubmit Error')
133 where_1 = {'id': Data.USER_ID,'nickname': '测试测试lalalallal'}
134 where_2 = {'user_id': Data.USER_ID,
135 'grade_id': 7,
136 'school_id': 68779,
137 'region_name': '浙江杭州西湖',
138 'region_id': 330106}
139 where_3 = {'user_id': Data.USER_ID,
140 'chinese': '北京出版社',
141 'english': '人民教育出版社',
142 'math': '人民教育出版社'
143 }
144 self.assertEqual(db_test.select_('acornuser.acorn_user', where_1), 1, 'RegisterExtrainfoSubmit Error')
145 self.assertEqual(db_test.select_('acornuser.ozing_student', where_2), 1, 'RegisterExtrainfoSubmit Error')
146 self.assertEqual(db_test.select_('acornuser.user_press', where_3), 1, 'RegisterExtrainfoSubmit Error')
147
148
149 #账户管理界面更换手机号绑定
150 class UpdateUserNameByUserId(unittest.TestCase):
151 def setUp(self):
152 self.base_url = HOST_BOSS + '/electronicCard/updateUserNameByUserId'
153 self.authCode_1 = CreateTestData.fet_authCode(Data.USER_PHONE_CHANGE_EXISTS)
154 self.authCode_2 = CreateTestData.fet_authCode(Data.USER_PHONE_CHANGE)
155 CreateTestData.pre_phoneUsedCheck(Data.USER_PHONE_CHANGE_EXISTS, True)
156 CreateTestData.pre_phoneUsedCheck(Data.USER_PHONE_CHANGE, False)
157
158 def tearDown(self):
159 print(self.result)
160
161 def test_UpdateUserNameByUserId_phoneExists_success(self):
162 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
163 postData = {
164 'username': Data.USER_PHONE_CHANGE_EXISTS,
165 'authCode': self.authCode_1,
166 'userId': Data.USER_ID
167 }
168 r = requests.post(self.base_url, headers=headers, data=postData)
169 self.result = r.json()
170 self.assertEqual(self.result['status'], 1006, 'UpdateUserNameByUserId_phoneExists Error')
171
172 def test_UpdateUserNameByUserId_success(self):
173 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
174 postData = {
175 'username': Data.USER_PHONE_CHANGE,
176 'authCode': self.authCode_2,
177 'userId': Data.USER_ID
178 }
179 r = requests.post(self.base_url, headers=headers, data=postData)
180 self.result = r.json()
181 self.assertEqual(self.result['status'], 1, 'UpdateUserNameByUserId Error')
182
183
184 # 添加用户反馈
185 class AddFeedBack(unittest.TestCase):
186 def setUp(self):
187 self.base_url = HOST_BOSS + '/feedback/add'
188 img_file = current_dir + '/1.png'
189 self.img = open(img_file, 'rb')
190
191 def tearDown(self):
192 print(self.result)
193
194 def test_AddFeedBack_success(self):
195 headers = {'Content-Type': 'multipart/form-data; boundary=fa0cada83b1d4b82a7ccd28ae8f7f6d6', 'Accept': '*/*'}
196 postData = {
197 'userId': Data.USER_ID,
198 'content': '11111feedback哦哦哦',
199 'contact': '00000000',
200 'feedtype': '个人中心'
201 }
202 file = {'imgs': self.img}
203
204 r = requests.post(self.base_url, data=postData, files=file)
205 #r = requests.post(self.base_url, headers=headers, data=postData)
206 ss = r.request
207 self.img.close()
208 self.result = r.json()
209 self.assertEqual(self.result['status'], 1, 'AddFeedBack Error')
210 select = {'userId': Data.USER_ID,
211 'content': '11111feedback哦哦哦',
212 'contact': '00000000',
213 'feedtype': '个人中心'}
214 self.assertTrue(db_test.select_('acornuser.feedback', select) > 0, 'AddFeedBack data insert Error')
215
216
217 # 获取最近观看视频列表
218 class GetRecentVideo(unittest.TestCase):
219 def setUp(self):
220 self.base_url = HOST_BOSS + '/personal/video/recent'
221 CreateTestData.pre_getRecentVideo(Data.USER_ID_NO_VIDEO, 0)
222 CreateTestData.pre_getRecentVideo(Data.USER_ID_VIDEO, 1)
223
224 def tearDown(self):
225 pass
226
227 def test_GetRecentVideo_noVideo_success(self):
228 getData = {'userId': Data.USER_ID_NO_VIDEO,
229 'pageNum': 1}
230 r = requests.get(self.base_url, params=getData)
231 self.result_1 = r.json()
232 self.assertEqual(self.result_1['status'], 1000, 'GetRecentVideo-noVideo fail')
233
234 def test_GetRecentVideo_success(self):
235 getData = {'userId': Data.USER_ID_VIDEO,
236 'pageNum': 1}
237 r = requests.get(self.base_url, params=getData)
238 self.result_2 = r.json()
239 self.assertEqual(self.result_2['status'], 1, 'GetRecentVideo fail')
240
241
242
243
244
test_cases/sub_account.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5 import requests
6 from data_fixture.config_data import HOST_BOSS
7 from data_fixture import create_testdata as CreateTestData
8 from data_fixture import config_data as Data
9 from data_fixture.mysql_db import DB
10 import uuid
11
12 db_test = DB()
13
14 #添加子账户
15 class AddSubAccount(unittest.TestCase):
16 def setUp(self):
17 self.base_url = HOST_BOSS + '/childUser/addChildUser'
18 CreateTestData.pre_AddSubAccount(Data.PARENT_ID)
19
20 def tearDown(self):
21 print(self.result)
22
23 def test_addSubAccount_success(self):
24 headers = {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*'}
25 postData = {'parentId': Data.PARENT_ID,
26 'image': Data.SUB_ACC_IMAGE,
27 'name': '测试sub',
28 'gradeId': '6',
29 'schoolId': Data.SUB_ACC_SCHOOL_ID_1,
30 'regionId': Data.SUB_ACC_REGION_ID_1,
31 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
32 'regionName': Data.SUB_ACC_REGION_NAME_1
33 }
34 r = requests.post(self.base_url, headers=headers, data=postData)
35 self.result = r.json()
36 self.assertEqual(db_test.select_('acornuser.child_user', {'parent_id': Data.PARENT_ID}), 1, 'addSubAccount Error')
37 self.assertEqual(self.result['status'], 1, 'addSubAccount Error')
38
39
40 #查找子账户信息
41 class GetSubAccount(unittest.TestCase):
42 def setUp(self):
43 self.base_url = HOST_BOSS + '/childUser/info'
44 self.subAccount_1 = str(uuid.uuid4()).replace('-', '')
45 self.subAccount_2 = str(uuid.uuid4()).replace('-', '')
46 CreateTestData.pre_subAccount(Data.PARENT_ID, self.subAccount_1, 0)
47 CreateTestData.pre_subAccount(Data.PARENT_ID, self.subAccount_2, 1)
48
49 def tearDown(self):
50 print(self.result)
51
52 def test_getSubAccount_success(self):
53 headers = {'Accept': '*/*'}
54 getData = {'userId': Data.PARENT_ID, 'deviceNumber':Data.DEVICE_NUMBER_CUS_BIND}
55 r = requests.get(self.base_url, headers=headers, params=getData)
56 self.result = r.json()
57 self.assertEqual(self.result['status'], 1, 'getSubAccount Error')
58 self.assertTrue(len(self.result['data']) > 1, 'getSubAccount data Error')
59
60
61 #删除子账户
62 class DelSubAccount(unittest.TestCase):
63 def setUp(self):
64 self.base_url = HOST_BOSS + '/childUser/delete'
65 self.subAccount = str(uuid.uuid4()).replace('-', '')
66 CreateTestData.pre_subAccount(Data.PARENT_ID, self.subAccount, 0)
67
68 def tearDown(self):
69 print(self.result)
70
71 def test_delSubAccount_success(self):
72 headers = {'Accept': '*/*'}
73 getData = {'subAccountId': self.subAccount}
74 r = requests.get(self.base_url, headers=headers, params=getData)
75 self.result = r.json()
76 self.assertEqual(db_test.select_('acornuser.child_user', {'subAccountId': self.subAccount}), 0, 'delSubAccount Error')
77 self.assertEqual(self.result['status'], 1, 'delSubAccount ERROR')
78
79
80 #切换账户
81 class SwitchAccounts(unittest.TestCase):
82 def setUp(self):
83 self.base_url = HOST_BOSS + '/childUser/update'
84 self.subAccount = str(uuid.uuid4()).replace('-', '')
85 CreateTestData.pre_subAccount(Data.PARENT_ID, self.subAccount, 0)
86
87 def tearDown(self):
88 print(self.result)
89
90 def test_swichToSubAccount_success(self):
91 headers = {'Accept': '*/*'}
92 getData = {'subAccountId': self.subAccount,
93 'userId': Data.PARENT_ID,
94 'deviceNumber' : Data.DEVICE_NUMBER_CUS_BIND,
95 'type': 2}
96 r = requests.get(self.base_url, headers=headers, params=getData)
97 self.result = r.json()
98 where_data = {'parent_id': Data.PARENT_ID,'subAccountId': self.subAccount, 'status':1}
99 self.assertEqual(db_test.select_('acornuser.child_user', where_data), 1, 'swichToSubAccount Error')
100 self.assertEqual(self.result['status'], 1, 'swichToSubAccount ERROR')
101
102 def test_swichToParentAccount_success(self):
103 headers = {'Accept': '*/*'}
104 getData = {'userId': Data.PARENT_ID,
105 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
106 'type': 1}
107 r = requests.get(self.base_url, headers=headers, params=getData)
108 self.result = r.json()
109 where_data = {'userId': Data.PARENT_ID,
110 'deviceNumber': Data.DEVICE_NUMBER_CUS_BIND,
111 'status': 1}
112 self.assertEqual(db_test.select_('acornuser.acorn_user_status', where_data), 1, 'swichToParentAccount Error')
113 self.assertEqual(self.result['status'], 1, 'swichToParentAccount ERROR')
114
115
116
117
118
119
test_cases/subject_sync.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5 import requests
6 from data_fixture.config_data import HOST_BOSS, HOST_STA, HOST_RES
7 from data_fixture import create_testdata as CreateTestData
8 from data_fixture import config_data as Data
9 from data_fixture.mysql_db import DB
10 import time
11 from datetime import date
12
13 db_test = DB()
14
15 #获取同步视频接口
16 class ClassNameVideo(unittest.TestCase):
17 def setUp(self):
18 self.base_url = HOST_RES + '/className/video'
19
20 def tearDown(self):
21 pass
22
23 def test_ClassNameVideo_success(self):
24 getData = {'textName': '秋天的怀念',
25 'press': '人民教育出版社',
26 'subject': '语文',
27 'gradeName': '7年级'}
28 r = requests.get(self.base_url, params=getData)
29 self.result_1 = r.json()
30 self.assertEqual(self.result_1['status'], 1, 'test_ClassNameVideo_success Error')
31
32 def test_ClassNameVideo_noData(self):
33 getData = {'textName': '秋天 的怀念',
34 'press': '人民教育出版社',
35 'subject': '语文',
36 'gradeName': '7年级'}
37 r = requests.get(self.base_url, params=getData)
38 self.result_2 = r.json()
39 self.assertEqual(self.result_2['status'], 1000, 'test_ClassNameVideo_noData Error')
40
41
42 #获取知识点视频
43 class PointVideo(unittest.TestCase):
44 def setUp(self):
45 self.base_url = HOST_RES + '/point/video'
46
47 def tearDown(self):
48 pass
49
50 def test_PointVideo_success(self):
51 getData = {'textName': '秋天的怀念',
52 'press': '人民教育出版社',
53 'subject': '语文',
54 'gradeName': '7年级',
55 'point':'说明文阅读5说明文的结构||议论文的定义和分类'}
56 r = requests.get(self.base_url, params=getData)
57 self.result_1 = r.json()
58 self.assertEqual(self.result_1['status'], 1, 'test_PointVideo_success Error')
59
60 def test_PointVideo_noData(self):
61 getData = {'textName': '秋天的怀念',
62 'press': '人民教育出版社',
63 'subject': '语文',
64 'gradeName': '7年级',
65 'point': '说明文阅读5说明文的结构'}
66 r = requests.get(self.base_url, params=getData)
67 self.result_2 = r.json()
68 self.assertEqual(self.result_2['status'], 1000, 'test_PointVideo_noData Error')
69
70
71 #课程中心PK练习抽题接口
72 class SubjectTest(unittest.TestCase):
73 def setUp(self):
74 self.base_url = HOST_BOSS + '/subject/test/'
75
76 def tearDown(self):
77 pass
78
79 def test_SubjectTest_success(self):
80 getData = {'subjectName': '数学',
81 'questionPoint': '二元一次方程||二元一次方程组的解',
82 'gradeId': '10',
83 'textName': '二元一次方程组'}
84 url = self.base_url + 'math'
85 r = requests.get(url, params=getData)
86 self.result_1 = r.json()
87 self.assertEqual(self.result_1['status'], 1, 'test_SubjectTest_success Error')
88
89
90 #巩固练习抽题接口
91 class ConsolidationExercise(unittest.TestCase):
92 def setUp(self):
93 self.base_url = HOST_BOSS + '/consolidation/exercise'
94
95 def tearDown(self):
96 pass
97
98 def test_ConsolidationExercise_success(self):
99 getData = {'subjectName': '数学',
100 'gradeId': '10',
101 'secondPoint': '二元一次方程||二元一次方程组的解',
102 'textName': '二元一次方程组',
103 'difficultyLevel': '基础卷'}
104 r = requests.get(self.base_url, params=getData)
105 self.result = r.json()
106 self.assertEqual(self.result['status'], 1, 'test_ConsolidationExercise_success Error')
107 self.assertTrue(len(self.result['data']) > 1)
108
109
110
111
112
test_suites/__pycache__/test_elecCard.cpython-36.pyc
No preview for this file type
test_suites/test_elecCard.py
File was created 1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import unittest
5
6 from test_cases import eleccard_setUp
7
8 from test_cases import eleccard_check
9
10 # 添加保卡
11 def suites_addElecCard():
12 suite = unittest.TestSuite()
13 suite.addTest(eleccard_check.CheckElecCardBind('test_checkElecCard_unbind'))
14 suite.addTest(eleccard_setUp.SetUpElecCard('test_addElecCard_success'))
15 suite.addTest(eleccard_check.CheckElecCardBind('test_checkElecCard_customerMachine'))
16 suite.addTest(eleccard_check.GetCardInfo('test_getCardInfo_success'))
17 return suite
18
19 # 客机置为样机
20 def suites_setElecCardtoSample():
21 suite = unittest.TestSuite()
22 # 机器是客机状态
23 suite.addTest(eleccard_check.CheckElecCardBind('test_checkElecCard_customerMachine'))
24 # 置为样机
25 suite.addTest(eleccard_setUp.SetToSample('test_updateToSample_success'))
26 # 检验判断为客机
27 suite.addTest(eleccard_check.CheckElecCardBind('test_checkElecCard_sampleMachine'))
28 return suite
29
30 # 样机置为客机
31 def suites_setElecCardtoCustomer():
32 suite = unittest.TestSuite()
33 # 机器是样机状态
34 suite.addTest(eleccard_check.CheckElecCardBind('test_checkElecCard_sampleMachine'))
35 # 置为客机
36 suite.addTest(eleccard_setUp.SetToCustomerMachine('test_updateToCustomer_success'))
37 # 检查需要添加保卡
38 suite.addTest(eleccard_check.CheckElecCardBind('test_checkElecCard_unbind'))
39
40 # 客机修改保卡
41
42
43 # 客机解绑保卡