Commit 631a27fe0dad5aca229f4186385488aad4662bee
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> |
.idea/misc.xml
| 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> |
.idea/vcs.xml
| 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,'&'); | ||
| 272 | s = s.replace(/</g,'<'); | ||
| 273 | s = s.replace(/>/g,'>'); | ||
| 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> </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'> </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,'&'); | ||
| 270 | s = s.replace(/</g,'<'); | ||
| 271 | s = s.replace(/>/g,'>'); | ||
| 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> </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'> </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 |
README
| 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
configParse.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 | 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,'&'); | ||
| 169 | s = s.replace(/</g,'<'); | ||
| 170 | s = s.replace(/>/g,'>'); | ||
| 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> </td> | ||
| 297 | </tr> | ||
| 298 | </table> | ||
| 299 | |||
| 300 | <div id='ending'> </div> | ||
| 301 | |||
| 302 | </body> | ||
| 303 | </html> | ||
| 304 |
run_test.py
| 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 |
run_test.pyc
No preview for this file type
test_cases/1.jpg
216 KB
test_cases/1.png
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 | # 客机解绑保卡 |