├── .gitignore
├── .idea
├── UItestframework.iml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── config
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-35.pyc
│ └── globalparam.cpython-35.pyc
├── config.ini
└── globalparam.py
├── data
└── testdata
│ └── searKey.xlsx
├── public
├── __init__.py
├── __pycache__
│ └── __init__.cpython-35.pyc
├── common
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── basepage.cpython-35.pyc
│ │ ├── datainfo.cpython-35.pyc
│ │ ├── log.cpython-35.pyc
│ │ ├── mytest.cpython-35.pyc
│ │ ├── pyselenium.cpython-35.pyc
│ │ ├── readconfig.cpython-35.pyc
│ │ └── sendmail.cpython-35.pyc
│ ├── basepage.py
│ ├── datainfo.py
│ ├── log.py
│ ├── mytest.py
│ ├── publicfunction.py
│ ├── pyselenium.py
│ ├── readconfig.py
│ └── sendmail.py
└── pages
│ ├── __init__.py
│ ├── __pycache__
│ ├── __init__.cpython-35.pyc
│ └── baiduIndexPage.cpython-35.pyc
│ └── baiduIndexPage.py
├── readme.md
├── report
├── log
│ └── 2016-11-08.log
└── testreport
│ └── TestResult2016-11-08_11_17_14.html
├── run.py
└── testcase
├── __pycache__
└── test_baidu.cpython-35.pyc
└── test_baidu.py
/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/.gitignore
--------------------------------------------------------------------------------
/.idea/UItestframework.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | true
105 | DEFINITION_ORDER
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 | project
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 | 1478222299195
505 |
506 |
507 | 1478222299195
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
--------------------------------------------------------------------------------
/config/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/config/__init__.py
--------------------------------------------------------------------------------
/config/__pycache__/__init__.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/config/__pycache__/__init__.cpython-35.pyc
--------------------------------------------------------------------------------
/config/__pycache__/globalparam.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/config/__pycache__/globalparam.cpython-35.pyc
--------------------------------------------------------------------------------
/config/config.ini:
--------------------------------------------------------------------------------
1 | [projectConfig]
2 | project_path=E:\Python-Project\UItestframework
3 |
--------------------------------------------------------------------------------
/config/globalparam.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | import os
4 | from public.common.readconfig import ReadConfig
5 |
6 | # 读取配置文件
7 | config_file_path = os.path.split(os.path.realpath(__file__))[0]
8 | read_config = ReadConfig(os.path.join(config_file_path,'config.ini'))
9 | # 项目参数设置
10 | prj_path = read_config.getValue('projectConfig','project_path')
11 | # 日志路径
12 | log_path = os.path.join(prj_path, 'report', 'log')
13 | # 截图文件路径
14 | img_path = os.path.join(prj_path, 'report', 'image')
15 | # 测试报告路径
16 | report_path = os.path.join(prj_path, 'report', 'testreport')
17 | # 默认浏览器
18 | browser = 'firefox'
19 |
20 | # 测试数据路径
21 | data_path = os.path.join(prj_path, 'data', 'testdata')
22 |
--------------------------------------------------------------------------------
/data/testdata/searKey.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/data/testdata/searKey.xlsx
--------------------------------------------------------------------------------
/public/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/__init__.py
--------------------------------------------------------------------------------
/public/__pycache__/__init__.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/__pycache__/__init__.cpython-35.pyc
--------------------------------------------------------------------------------
/public/common/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/common/__init__.py
--------------------------------------------------------------------------------
/public/common/__pycache__/__init__.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/common/__pycache__/__init__.cpython-35.pyc
--------------------------------------------------------------------------------
/public/common/__pycache__/basepage.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/common/__pycache__/basepage.cpython-35.pyc
--------------------------------------------------------------------------------
/public/common/__pycache__/datainfo.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/common/__pycache__/datainfo.cpython-35.pyc
--------------------------------------------------------------------------------
/public/common/__pycache__/log.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/common/__pycache__/log.cpython-35.pyc
--------------------------------------------------------------------------------
/public/common/__pycache__/mytest.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/common/__pycache__/mytest.cpython-35.pyc
--------------------------------------------------------------------------------
/public/common/__pycache__/pyselenium.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/common/__pycache__/pyselenium.cpython-35.pyc
--------------------------------------------------------------------------------
/public/common/__pycache__/readconfig.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/common/__pycache__/readconfig.cpython-35.pyc
--------------------------------------------------------------------------------
/public/common/__pycache__/sendmail.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/common/__pycache__/sendmail.cpython-35.pyc
--------------------------------------------------------------------------------
/public/common/basepage.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | class Page(object):
4 | """
5 | This is a base page class for Page Object.
6 | """
7 | def __init__(self, selenium_driver):
8 | self.dr = selenium_driver
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/public/common/datainfo.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | import codecs
4 | import os
5 | import xlrd
6 | from config import globalparam
7 |
8 | data_path = globalparam.data_path
9 | def get_xls_to_dict(xlsname, sheetname):
10 | """
11 | 读取excel表结果为dict
12 | 第一行为字典的key,下面的为值
13 | return [{'title':'1','user':'root'},{'title':'2','user':'xiaoshitou'}]
14 | """
15 | # dataresult = []
16 | # result = []
17 | datapath = os.path.join(data_path,xlsname)
18 | xls1 = xlrd.open_workbook(datapath)
19 | table = xls1.sheet_by_name(sheetname)
20 | # for i in range(0,table.nrows):
21 | # dataresult.append(table.row_values(i))
22 | dataresult = [table.row_values(i) for i in range(0, tabl.nrows)]
23 | #将list转化成dict
24 | # for i in range(1,len(dataresult)):
25 | # temp = dict(zip(dataresult[0],dataresult[i]))
26 | # result.append(temp)
27 |
28 | result = [ dict(zip(dataresult[0], dataresult[i])) for i in range(1, len(dataresult))]
29 | return result
30 |
31 | def get_url_data(title):
32 | """
33 | 读取txt文件,转化成dict;读取url和导航栏的对应关系
34 | 将txt转化成一个字典:下单=>/admin/order/index
35 | {'title1':'url1','下单':'/admin/order/index'}
36 | """
37 | name = 'urlsource.txt'
38 | txtpath = os.path.join(data_path,name)
39 | with codecs.open(txtpath,'r',encoding='utf-8') as f:
40 | txtcontent = f.readlines()
41 | txtdict = dict([txt.strip().replace('\ufeff','').split('=>') for txt in txtcontent])
42 | return txtdict[title]
43 |
44 | def get_xls_to_list(excelname, sheetname):
45 | """
46 | 读取excel表,返回一个list,只是返回第一列的值
47 | return [1,2,3,4,5]
48 | """
49 | datapath = os.path.join(data_path, excelname)
50 | excel = xlrd.open_workbook(datapath)
51 | table = excel.sheet_by_name(sheetname)
52 | result = [table.row_values(i)[0].strip() for i in range(1,table.nrows)]
53 | return result
54 |
55 | if __name__=='__main__':
56 | res = get_xls_to_list('addressParse.xlsx','Sheet1')
57 | res = get_xls_to_dict('admin_single_order.xlsx','ordermsg')
58 | print(res)
59 |
60 |
61 |
--------------------------------------------------------------------------------
/public/common/log.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | import logging
4 | import time
5 | import os
6 | from config import globalparam
7 |
8 | log_path = globalparam.log_path
9 | class Log:
10 | def __init__(self):
11 | self.logname = os.path.join(log_path, '{0}.log'.format(time.strftime('%Y-%m-%d')))
12 |
13 | def __printconsole(self, level, message):
14 | # 创建一个logger
15 | logger = logging.getLogger()
16 | logger.setLevel(logging.DEBUG)
17 | # 创建一个handler,用于写入日志文件
18 | fh = logging.FileHandler(self.logname,'a',encoding='utf-8')
19 | fh.setLevel(logging.DEBUG)
20 | # 再创建一个handler,用于输出到控制台
21 | ch = logging.StreamHandler()
22 | ch.setLevel(logging.DEBUG)
23 | # 定义handler的输出格式
24 | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
25 | fh.setFormatter(formatter)
26 | ch.setFormatter(formatter)
27 | # 给logger添加handler
28 | logger.addHandler(fh)
29 | logger.addHandler(ch)
30 | # 记录一条日志
31 | if level == 'info':
32 | logger.info(message)
33 | elif level == 'debug':
34 | logger.debug(message)
35 | elif level == 'warning':
36 | logger.warning(message)
37 | elif level == 'error':
38 | logger.error(message)
39 | logger.removeHandler(ch)
40 | logger.removeHandler(fh)
41 | # 关闭打开的文件
42 | fh.close()
43 |
44 | def debug(self,message):
45 | self.__printconsole('debug', message)
46 |
47 | def info(self,message):
48 | self.__printconsole('info', message)
49 |
50 | def warning(self,message):
51 | self.__printconsole('warning', message)
52 |
53 | def error(self,message):
54 | self.__printconsole('error', message)
55 |
--------------------------------------------------------------------------------
/public/common/mytest.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | import unittest
4 | from public.common import pyselenium
5 | from config import globalparam
6 | from public.common.log import Log
7 |
8 |
9 | class MyTest(unittest.TestCase):
10 | """
11 | The base class is for all testcase.
12 | """
13 | def setUp(self):
14 | self.logger = Log()
15 | self.logger.info('############################### START ###############################')
16 | self.dr = pyselenium.PySelenium(globalparam.browser)
17 | self.dr.max_window()
18 |
19 | def tearDown(self):
20 | self.dr.quit()
21 | self.logger.info('############################### End ###############################')
22 |
--------------------------------------------------------------------------------
/public/common/publicfunction.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | from config import globalparam
4 |
5 |
6 | # 截图放到report下的img目录下
7 | def get_img(dr, filename):
8 | path = globalparam.img_path + '\\' + filename
9 | dr.take_screenshot(path)
10 |
11 |
--------------------------------------------------------------------------------
/public/common/pyselenium.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 |
3 | import time
4 | from selenium import webdriver
5 | from selenium.webdriver.common.action_chains import ActionChains
6 | from selenium.webdriver.support import expected_conditions as EC
7 | from selenium.webdriver.support.ui import WebDriverWait
8 | from selenium.webdriver.common.by import By
9 | from selenium.webdriver.common.keys import Keys
10 | from selenium.common.exceptions import TimeoutException
11 | from public.common.log import Log
12 |
13 | success = "SUCCESS "
14 | fail = "FAIL "
15 | logger = Log()
16 |
17 | class PySelenium(object):
18 | """
19 | pyselenium framework for the main class, the original
20 | selenium provided by the method of the two packaging,
21 | making it easier to use.
22 | """
23 |
24 | def __init__(self, browser='ff', remoteAddress=None):
25 | """
26 | remote consle:
27 | dr = PySelenium('RChrome','127.0.0.1:8080')
28 | """
29 | t1 = time.time()
30 | dc = {'platform': 'ANY', 'browserName': 'chrome', 'version': '', 'javascriptEnabled': True}
31 | dr = None
32 | if remoteAddress is None:
33 | if browser == "firefox" or browser == "ff":
34 | dr = webdriver.Firefox()
35 | elif browser == "chrome" or browser == "Chrome":
36 | dr = webdriver.Chrome()
37 | elif browser == "internet explorer" or browser == "ie":
38 | dr = webdriver.Ie()
39 | elif browser == "opera":
40 | dr = webdriver.Opera()
41 | elif browser == "phantomjs":
42 | dr = webdriver.PhantomJS()
43 | elif browser == "edge":
44 | dr = webdriver.Edge()
45 | else:
46 | if browser == "RChrome":
47 | dr = webdriver.Remote(command_executor='http://' + remoteAddress + '/wd/hub',
48 | desired_capabilities=dc)
49 | elif browser == "RIE":
50 | dc['browserName'] = 'internet explorer'
51 | dr = webdriver.Remote(command_executor='http://' + remoteAddress + '/wd/hub',
52 | desired_capabilities=dc)
53 | elif browser == "RFirefox":
54 | dc['browserName'] = 'firefox'
55 | dc['marionette'] = False
56 | dr = webdriver.Remote(command_executor='http://' + remoteAddress + '/wd/hub',
57 | desired_capabilities=dc)
58 | try:
59 | self.driver = dr
60 | self.my_print("{0} Start a new browser: {1}, Spend {2} seconds".format(success,browser,time.time()-t1))
61 | except Exception:
62 | raise NameError("Not found {0} browser,You can enter 'ie','ff',"
63 | "'chrome','RChrome','RIe' or 'RFirefox'.".format( browser))
64 |
65 | def my_print(self,msg):
66 | logger.info(msg)
67 |
68 | def element_wait(self, css, secs=5):
69 | """
70 | Waiting for an element to display.
71 |
72 | Usage:
73 | driver.element_wait("id->kw",10)
74 | """
75 | if "->" not in css:
76 | raise NameError("Positioning syntax errors, lack of '->'.")
77 |
78 | by = css.split("->")[0].strip()
79 | value = css.split("->")[1].strip()
80 | messages = 'Element: {0} not found in {1} seconds.'.format(css, secs)
81 |
82 | if by == "id":
83 | WebDriverWait(self.driver, secs, 1).until(EC.presence_of_element_located((By.ID, value)), messages)
84 | elif by == "name":
85 | WebDriverWait(self.driver, secs, 1).until(EC.presence_of_element_located((By.NAME, value)), messages)
86 | elif by == "class":
87 | WebDriverWait(self.driver, secs, 1).until(EC.presence_of_element_located((By.CLASS_NAME, value)), messages)
88 | elif by == "link_text":
89 | WebDriverWait(self.driver, secs, 1).until(EC.presence_of_element_located((By.LINK_TEXT, value)), messages)
90 | elif by == "xpath":
91 | WebDriverWait(self.driver, secs, 1).until(EC.presence_of_element_located((By.XPATH, value)), messages)
92 | elif by == "css":
93 | WebDriverWait(self.driver, secs, 1).until(EC.presence_of_element_located((By.CSS_SELECTOR, value)),messages)
94 | else:
95 | raise NameError("Please enter the correct targeting elements,'id','name','class','link_text','xpaht','css'.")
96 |
97 | def get_element(self, css):
98 | """
99 | Judge element positioning way, and returns the element.
100 |
101 | Usage:
102 | driver.get_element('id->kw')
103 | """
104 | if "->" not in css:
105 | raise NameError("Positioning syntax errors, lack of '->'.")
106 |
107 | by = css.split("->")[0].strip()
108 | value = css.split("->")[1].strip()
109 |
110 | if by == "id":
111 | element = self.driver.find_element_by_id(value)
112 | elif by == "name":
113 | element = self.driver.find_element_by_name(value)
114 | elif by == "class":
115 | element = self.driver.find_element_by_class_name(value)
116 | elif by == "link_text":
117 | element = self.driver.find_element_by_link_text(value)
118 | elif by == "xpath":
119 | element = self.driver.find_element_by_xpath(value)
120 | elif by == "css":
121 | element = self.driver.find_element_by_css_selector(value)
122 | else:
123 | raise NameError("Please enter the correct targeting elements,'id','name','class','link_text','xpaht','css'.")
124 | return element
125 |
126 | def open(self, url):
127 | """
128 | open url.
129 |
130 | Usage:
131 | driver.open("https://www.baidu.com")
132 | """
133 | t1 = time.time()
134 | try:
135 | self.driver.get(url)
136 | self.my_print("{0} Navigated to {1}, Spend {2} seconds".format(success,url,time.time()-t1))
137 | except Exception:
138 | self.my_print("{0} Unable to load {1}, Spend {2} seconds".format(fail, url, time.time() - t1))
139 | raise
140 |
141 | def max_window(self):
142 | """
143 | Set browser window maximized.
144 |
145 | Usage:
146 | driver.max_window()
147 | """
148 | t1 = time.time()
149 | self.driver.maximize_window()
150 | self.my_print("{0} Set browser window maximized, Spend {1} seconds".format(success, time.time() - t1))
151 |
152 | def set_window(self, wide, high):
153 | """
154 | Set browser window wide and high.
155 |
156 | Usage:
157 | driver.set_window(wide,high)
158 | """
159 | t1 = time.time()
160 | self.driver.set_window_size(wide, high)
161 | self.my_print("{0} Set browser window wide: {1},high: {2}, Spend {3} seconds".format(success,
162 | wide,high,time.time() - t1))
163 |
164 | def type(self, css, text):
165 | """
166 | Operation input box.
167 |
168 | Usage:
169 | driver.type("id->kw","selenium")
170 | """
171 | t1 = time.time()
172 | try:
173 | self.element_wait(css)
174 | el = self.get_element(css)
175 | el.send_keys(text)
176 | self.my_print("{0} Typed element: <{1}> content: {2}, Spend {3} seconds".format(success,
177 | css,text,time.time() - t1))
178 | except Exception:
179 | self.my_print("{0} Unable to type element: <{1}> content: {2}, Spend {3} seconds".format(fail,
180 | css, text, time.time() - t1))
181 | raise
182 |
183 | def clear_type(self, css, text):
184 | """
185 | Clear and input element.
186 |
187 | Usage:
188 | driver.clear_type("id->kw","selenium")
189 | """
190 | t1 = time.time()
191 | try:
192 | self.element_wait(css)
193 | el = self.get_element(css)
194 | el.clear()
195 | el.send_keys(text)
196 | self.my_print("{0} Clear and type element: <{1}> content: {2}, Spend {3} seconds".format(success,
197 | css, text,time.time() - t1))
198 | except Exception:
199 | self.my_print("{0} Unable to clear and type element: <{1}> content: {2}, Spend {3} seconds".format(fail,
200 | css, text,time.time() - t1))
201 | raise
202 |
203 | def click(self, css):
204 | """
205 | It can click any text / image can be clicked
206 | Connection, check box, radio buttons, and even drop-down box etc..
207 |
208 | Usage:
209 | driver.click("id->kw")
210 | """
211 | t1 = time.time()
212 | try:
213 | self.element_wait(css)
214 | el = self.get_element(css)
215 | el.click()
216 | self.my_print("{0} Clicked element: <{1}>, Spend {2} seconds".format(success,css,time.time() - t1))
217 | except Exception:
218 | self.my_print("{0} Unable to click element: <{1}>, Spend {2} seconds".format(fail, css, time.time() - t1))
219 | raise
220 |
221 | def right_click(self, css):
222 | """
223 | Right click element.
224 |
225 | Usage:
226 | driver.right_click("id->kw")
227 | """
228 | t1 = time.time()
229 | try:
230 | self.element_wait(css)
231 | el = self.get_element(css)
232 | ActionChains(self.driver).context_click(el).perform()
233 | self.my_print("{0} Right click element: <{1}>, Spend {2} seconds".format(success, css, time.time() - t1))
234 | except Exception:
235 | self.my_print("{0} Unable to right click element: <{1}>, Spend {2} seconds".format(fail, css, time.time() - t1))
236 | raise
237 |
238 | def move_to_element(self, css):
239 | """
240 | Mouse over the element.
241 |
242 | Usage:
243 | driver.move_to_element("id->kw")
244 | """
245 | t1 = time.time()
246 | try:
247 | self.element_wait(css)
248 | el = self.get_element(css)
249 | ActionChains(self.driver).move_to_element(el).perform()
250 | self.my_print("{0} Move to element: <{1}>, Spend {2} seconds".format(success, css, time.time() - t1))
251 | except Exception:
252 | self.my_print("{0} unable move to element: <{1}>, Spend {2} seconds".format(fail, css, time.time() - t1))
253 | raise
254 |
255 | def double_click(self, css):
256 | """
257 | Double click element.
258 |
259 | Usage:
260 | driver.double_click("id->kw")
261 | """
262 | t1 = time.time()
263 | try:
264 | self.element_wait(css)
265 | el = self.get_element(css)
266 | ActionChains(self.driver).double_click(el).perform()
267 | self.my_print("{0} Double click element: <{1}>, Spend {2} seconds".format(success, css, time.time() - t1))
268 | except Exception:
269 | self.my_print("{0} Unable to double click element: <{1}>, Spend {2} seconds".format(fail, css, time.time() - t1))
270 | raise
271 |
272 | def drag_and_drop(self, el_css, ta_css):
273 | """
274 | Drags an element a certain distance and then drops it.
275 |
276 | Usage:
277 | driver.drag_and_drop("id->kw","id->su")
278 | """
279 | t1 = time.time()
280 | try:
281 | self.element_wait(el_css)
282 | element = self.get_element(el_css)
283 | self.element_wait(ta_css)
284 | target = self.get_element(ta_css)
285 | ActionChains(driver).drag_and_drop(element, target).perform()
286 | self.my_print("{0} Drag and drop element: <{1}> to element: <{2}>, Spend {3} seconds".format(success,
287 | el_css,ta_css, time.time() - t1))
288 | except Exception:
289 | self.my_print("{0} Unable to drag and drop element: <{1}> to element: <{2}>, Spend {3} seconds".format(fail,
290 | el_css, ta_css, time.time() - t1))
291 | raise
292 |
293 | def click_text(self, text):
294 | """
295 | Click the element by the link text
296 |
297 | Usage:
298 | driver.click_text("新闻")
299 | """
300 | t1 = time.time()
301 | try:
302 | self.driver.find_element_by_partial_link_text(text).click()
303 | self.my_print("{0} Click by text content: {1}, Spend {2} seconds".format(success, text,time.time() - t1))
304 | except Exception:
305 | self.my_print("{0} Unable to Click by text content: {1}, Spend {2} seconds".format(fail, text, time.time() - t1))
306 | raise
307 |
308 | def close(self):
309 | """
310 | Simulates the user clicking the "close" button in the titlebar of a popup
311 | window or tab.
312 |
313 | Usage:
314 | driver.close()
315 | """
316 | t1 = time.time()
317 | self.driver.close()
318 | self.my_print("{0} Closed current window, Spend {1} seconds".format(success, time.time() - t1))
319 |
320 | def quit(self):
321 | """
322 | Quit the driver and close all the windows.
323 |
324 | Usage:
325 | driver.quit()
326 | """
327 | t1 = time.time()
328 | self.driver.quit()
329 | self.my_print("{0} Closed all window and quit the driver, Spend {1} seconds".format(success, time.time() - t1))
330 |
331 | def submit(self, css):
332 | """
333 | Submit the specified form.
334 |
335 | Usage:
336 | driver.submit("id->kw")
337 | """
338 | t1 = time.time()
339 | try:
340 | self.element_wait(css)
341 | el = self.get_element(css)
342 | el.submit()
343 | self.my_print("{0} Submit form args element: <{1}>, Spend {2} seconds".format(success,css, time.time() - t1))
344 | except Exception:
345 | self.my_print("{0} Unable to submit form args element: <{1}>, Spend {2} seconds".format(fail, css, time.time() - t1))
346 | raise
347 |
348 | def F5(self):
349 | """
350 | Refresh the current page.
351 |
352 | Usage:
353 | driver.F5()
354 | """
355 | t1 = time
356 | self.driver.refresh()
357 | self.my_print("{0} Refresh the current page, Spend {1} seconds".format(success, time.time() - t1))
358 |
359 | def js(self, script):
360 | """
361 | Execute JavaScript scripts.
362 |
363 | Usage:
364 | driver.js("window.scrollTo(200,1000);")
365 | """
366 | t1 = time.time()
367 | try:
368 | self.driver.execute_script(script)
369 | self.my_print("{0} Execute javascript scripts: {1}, Spend {2} seconds".format(success,script, time.time() - t1))
370 | except Exception:
371 | self.my_print("{0} Unable to execute javascript scripts: {1}, Spend {2} seconds".format(fail,
372 | script, time.time() - t1))
373 | raise
374 |
375 | def get_attribute(self, css, attribute):
376 | """
377 | Gets the value of an element attribute.
378 |
379 | Usage:
380 | driver.get_attribute("id->su","href")
381 | """
382 | t1 = time.time()
383 | try:
384 | el = self.get_element(css)
385 | attr = el.get_attribute(attribute)
386 | self.my_print("{0} Get attribute element: <{1}>,attribute: {2}, Spend {3} seconds".format(success,
387 | css,attribute,time.time()-t1))
388 | return attr
389 | except Exception:
390 | self.my_print("{0} Unable to get attribute element: <{1}>,attribute: {2}, Spend {3} seconds".format(fail,
391 | css, attribute,time.time() - t1))
392 | raise
393 |
394 | def get_text(self, css):
395 | """
396 | Get element text information.
397 |
398 | Usage:
399 | driver.get_text("id->kw")
400 | """
401 | t1 = time.time()
402 | try:
403 | self.element_wait(css)
404 | text = self.get_element(css).text
405 | self.my_print("{0} Get element text element: <{1}>, Spend {2} seconds".format(success,css,time.time()-t1))
406 | return text
407 | except Exception:
408 | self.my_print("{0} Unable to get element text element: <{1}>, Spend {2} seconds".format(fail, css, time.time() - t1))
409 | raise
410 |
411 | def get_title(self):
412 | """
413 | Get window title.
414 |
415 | Usage:
416 | driver.get_title()
417 | """
418 |
419 | t1 = time.time()
420 | title = self.driver.title
421 | self.my_print("{0} Get current window title, Spend {1} seconds".format(success, time.time() - t1))
422 | return title
423 |
424 | def get_url(self):
425 | """
426 | Get the URL address of the current page.
427 |
428 | Usage:
429 | driver.get_url()
430 | """
431 | t1 = time.time()
432 | url = self.driver.current_url
433 | self.my_print("{0} Get current window url, Spend {1} seconds".format(success, time.time() - t1))
434 | return url
435 |
436 | def wait(self, secs):
437 | """
438 | Implicitly wait.All elements on the page.
439 |
440 | Usage:
441 | driver.wait(10)
442 | """
443 | t1 = time.time()
444 | self.driver.implicitly_wait(secs)
445 | self.my_print("{0} Set wait all element display in {1} seconds, Spend {2} seconds".format(success,
446 | secs,time.time() - t1))
447 |
448 | def accept_alert(self):
449 | """
450 | Accept warning box.
451 |
452 | Usage:
453 | driver.accept_alert()
454 | """
455 | t1 = time.time()
456 | self.driver.switch_to.alert.accept()
457 | self.my_print("{0} Accept warning box, Spend {1} seconds".format(success, time.time() - t1))
458 |
459 | def dismiss_alert(self):
460 | """
461 | Dismisses the alert available.
462 |
463 | Usage:
464 | driver.dismiss_alert()
465 | """
466 | t1 = time.time()
467 | self.driver.switch_to.alert.dismiss()
468 | self.my_print("{0} Dismisses the alert available, Spend {1} seconds".format(success, time.time() - t1))
469 |
470 | def switch_to_frame(self, css):
471 | """
472 | Switch to the specified frame.
473 |
474 | Usage:
475 | driver.switch_to_frame("id->kw")
476 | """
477 | t1 = time.time()
478 | try:
479 | self.element_wait(css)
480 | iframe_el = self.get_element(css)
481 | self.driver.switch_to.frame(iframe_el)
482 | self.my_print("{0} Switch to frame element: <{1}>, Spend {2} seconds".format(success,css, time.time() - t1))
483 | except Exception:
484 | self.my_print("{0} Unable switch to frame element: <{1}>, Spend {2} seconds".format(fail, css, time.time() - t1))
485 | raise
486 |
487 | def switch_to_frame_out(self):
488 | """
489 | Returns the current form machine form at the next higher level.
490 | Corresponding relationship with switch_to_frame () method.
491 |
492 | Usage:
493 | driver.switch_to_frame_out()
494 | """
495 | t1 = time.time()
496 | self.driver.switch_to.default_content()
497 | self.my_print("{0} Switch to frame out, Spend {1} seconds".format(success, time.time() - t1))
498 |
499 | def open_new_window(self, css):
500 | """
501 | Open the new window and switch the handle to the newly opened window.
502 |
503 | Usage:
504 | driver.open_new_window("id->kw")
505 | """
506 | t1 = time.time()
507 | try:
508 | original_windows = self.driver.current_window_handle
509 | el = self.get_element(css)
510 | el.click()
511 | all_handles = self.driver.window_handles
512 | for handle in all_handles:
513 | if handle != original_windows:
514 | self.driver.switch_to.window(handle)
515 | self.my_print("{0} Click element: <{1}> open a new window and swich into, Spend {2} seconds".format(success,
516 | css,time.time() - t1))
517 | except Exception:
518 | self.my_print("{0} Click element: <{1}> open a new window and swich into, Spend {2} seconds".format(fail,
519 | css,time.time() - t1))
520 | raise
521 |
522 | def element_exist(self, css):
523 | """
524 | judge element is exist,The return result is true or false.
525 |
526 | Usage:
527 | driver.element_exist("id->kw")
528 | """
529 | t1 = time.time()
530 | try:
531 | self.element_wait(css)
532 | self.my_print("{0} Element: <{1}> is exist, Spend {2} seconds".format(success,css, time.time() - t1))
533 | return True
534 | except TimeoutException:
535 | self.my_print("{0} Element: <{1}> is not exist, Spend {2} seconds".format(fail, css, time.time() - t1))
536 | return False
537 |
538 | def take_screenshot(self, file_path):
539 | """
540 | Get the current window screenshot.
541 |
542 | Usage:
543 | driver.take_screenshot('c:/test.png')
544 | """
545 | t1 = time.time()
546 | try:
547 | self.driver.get_screenshot_as_file(file_path)
548 | self.my_print("{0} Get the current window screenshot,path: {1}, Spend {2} seconds".format(success,
549 | file_path, time.time() - t1))
550 | except Exception:
551 | self.my_print("{0} Unable to get the current window screenshot,path: {1}, Spend {2} seconds".format(fail,
552 | file_path,time.time() - t1))
553 | raise
554 |
555 | def into_new_window(self):
556 | """
557 | Into the new window.
558 |
559 | Usage:
560 | dirver.into_new_window()
561 | """
562 | t1 = time.time()
563 | try:
564 | all_handle = self.driver.window_handles
565 | flag = 0
566 | while len(all_handle) < 2:
567 | time.sleep(1)
568 | all_handle = self.driver.window_handles
569 | flag += 1
570 | if flag == 5:
571 | break
572 | self.driver.switch_to.window(all_handle[-1])
573 | self.my_print("{0} Switch to the new window,new window's url: {1}, Spend {2} seconds".format(success,
574 | self.driver.current_url,time.time() - t1))
575 | except Exception:
576 | self.my_print("{0} Unable switch to the new window, Spend {1} seconds".format(fail, time.time() - t1))
577 | raise
578 |
579 | def type_and_enter(self, css, text, secs=0.5):
580 | """
581 | Operation input box. 1、input message,sleep 0.5s;2、input ENTER.
582 |
583 | Usage:
584 | driver.type_css_keys('id->kw','beck')
585 | """
586 | t1 = time.time()
587 | try:
588 | self.element_wait(css)
589 | ele = self.get_element(css)
590 | ele.send_keys(text)
591 | time.sleep(secs)
592 | ele.send_keys(Keys.ENTER)
593 | self.my_print("{0} Element <{1}> type content: {2},and sleep {3} seconds,input ENTER key, Spend {4} seconds".format(
594 | success,css,text,secs,time.time() - t1))
595 | except Exception:
596 | self.my_print("{0} Unable element <{1}> type content: {2},and sleep {3} seconds,input ENTER key, Spend {4} seconds".
597 | format(fail, css, text, secs, time.time() - t1))
598 | raise
599 |
600 | def js_click(self, css):
601 | """
602 | Input a css selecter,use javascript click element.
603 |
604 | Usage:
605 | driver.js_click('#buttonid')
606 | """
607 | t1 = time.time()
608 | js_str = "$('{0}').click()".format(css)
609 | try:
610 | self.driver.execute_script(js_str)
611 | self.my_print("{0} Use javascript click element: {1}, Spend {2} seconds".format(success,js_str,time.time()-t1))
612 | except Exception:
613 | self.my_print("{0} Unable to use javascript click element: {1}, Spend {2} seconds".format(fail,
614 | js_str, time.time() - t1))
615 | raise
616 |
617 | @property
618 | def origin_driver(self):
619 | """
620 | Return the original driver,Can use webdriver API.
621 |
622 | Usage:
623 | driver.origin_driver
624 | """
625 | return self.driver
626 |
627 |
628 | if __name__ == '__main__':
629 | driver = PySelenium("chrome")
630 |
--------------------------------------------------------------------------------
/public/common/readconfig.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | import configparser
4 | import codecs
5 |
6 | class ReadConfig:
7 | """
8 | 专门读取配置文件的,.ini文件格式
9 | """
10 | def __init__(self, filename):
11 | # configpath = os.path.join(prjDir,filename)
12 | configpath = filename
13 | # print(configpath)
14 | fd = open(configpath)
15 | data = fd.read()
16 | # remove BOM
17 | if data[:3] == codecs.BOM_UTF8:
18 | data = data[3:]
19 | files = codecs.open(configpath, "w")
20 | files.write(data)
21 | files.close()
22 | fd.close()
23 |
24 | self.cf = configparser.ConfigParser()
25 | self.cf.read(configpath)
26 |
27 | def getValue(self, env, name):
28 | """
29 | [projectConfig]
30 | project_path=E:/Python-Project/UItestframework
31 | :param env:[projectConfig]
32 | :param name:project_path
33 | :return:E:/Python-Project/UItestframework
34 | """
35 | return self.cf.get(env,name)
36 |
37 |
--------------------------------------------------------------------------------
/public/common/sendmail.py:
--------------------------------------------------------------------------------
1 | #coding:utf-8
2 |
3 | import os
4 | import smtplib
5 | import time
6 | from email.mime.text import MIMEText
7 | from email.mime.multipart import MIMEMultipart
8 | from public.common.log import Log
9 | from config import globalparam
10 |
11 | # 测试报告的路径
12 | reportPath = globalparam.report_path
13 | logger = Log()
14 | # 配置收发件人
15 | recvaddress = ['xxx.xx@xxx.com','xxxx@qq.com']
16 | # 163的用户名和密码
17 | sendaddr_name = 'xxxxx@163.com'
18 | sendaddr_pswd = 'xxxxx'
19 |
20 | class SendMail:
21 | def __init__(self,recver=None):
22 | """接收邮件的人:list or tuple"""
23 | if recver is None:
24 | self.sendTo = recvaddress
25 | else:
26 | self.sendTo = recver
27 |
28 | def __get_report(self):
29 | """获取最新测试报告"""
30 | dirs = os.listdir(reportPath)
31 | dirs.sort()
32 | newreportname = dirs[-1]
33 | print('The new report name: {0}'.format(newreportname))
34 | return newreportname
35 |
36 | def __take_messages(self):
37 | """生成邮件的内容,和html报告附件"""
38 | newreport = self.__get_report()
39 | self.msg = MIMEMultipart()
40 | self.msg['Subject'] = '测试报告主题'
41 | self.msg['date'] = time.strftime('%a, %d %b %Y %H:%M:%S %z')
42 |
43 | with open(os.path.join(reportPath,newreport), 'rb') as f:
44 | mailbody = f.read()
45 | html = MIMEText(mailbody,_subtype='html',_charset='utf-8')
46 | self.msg.attach(html)
47 |
48 | # html附件
49 | att1 = MIMEText(mailbody, 'base64', 'gb2312')
50 | att1["Content-Type"] = 'application/octet-stream'
51 | att1["Content-Disposition"] = 'attachment; filename="TestReport.html"'#这里的filename可以任意写,写什么名字,邮件中显示什么名字
52 | self.msg.attach(att1)
53 |
54 | def send(self):
55 | """发送邮件"""
56 | self.__take_messages()
57 | self.msg['from'] = sendaddr_name
58 | try:
59 | smtp = smtplib.SMTP('smtp.163.com',25)
60 | smtp.login(sendaddr_name,sendaddr_pswd)
61 | smtp.sendmail(self.msg['from'], self.sendTo,self.msg.as_string())
62 | smtp.close()
63 | logger.info("发送邮件成功")
64 | except Exception:
65 | logger.error('发送邮件失败')
66 | raise
67 |
68 | if __name__ == '__main__':
69 | sendMail = SendMail()
70 | sendMail.send()
71 |
72 |
73 |
--------------------------------------------------------------------------------
/public/pages/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/pages/__init__.py
--------------------------------------------------------------------------------
/public/pages/__pycache__/__init__.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/pages/__pycache__/__init__.cpython-35.pyc
--------------------------------------------------------------------------------
/public/pages/__pycache__/baiduIndexPage.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/public/pages/__pycache__/baiduIndexPage.cpython-35.pyc
--------------------------------------------------------------------------------
/public/pages/baiduIndexPage.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | from public.common import basepage
4 |
5 | class BaiduIndexPage(basepage.Page):
6 |
7 | def into_baidu_page(self):
8 | """打开百度首页"""
9 | self.dr.open('http://www.baidu.com')
10 | def input_search_key(self,values):
11 | """输入搜索关键词"""
12 | self.dr.clear_type('id->kw',values)
13 |
14 | def click_search_button(self):
15 | """点击搜索按钮"""
16 | self.dr.click('id->su')
17 |
18 | def return_title(self):
19 | """返回该页面的title"""
20 | return self.dr.get_title()
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
UItestframework项目目前具有以下功能:
1、对webdriver进行了第二次的简单封装,使用更加方便 public/common/pyselenium.py
(ps:这个是在虫师的pyse基础加了打印日志功能,参考:https://github.com/defnngj/pyse)
2、可以对excel表进行数据读取,完成数据驱动:public/common/datainfo.py
3、具有打印日志的功能,打印在控制台和文件中:public/common/log.py,日志保存在report/log/目录下
4、读取配置文件(.ini文件):public/common/readconfig.py
5、具有发邮件的功能:public/common/sendmail.py
6、生成测试报告:html测试报告的路径:report/testreport/目录下
7、使用了PageObject模式来编写测试脚本
整个项目的目录结构:
├─config 配置文件的目录
│ │ config.ini 存放配置文件
│ │ globalparam.py 重要的全局参数,如log、report的路径配置等
│ │ __init__.py
│ │
│
├─data 测试数据
│ ├─formaldata # 正式环境测试数据
│ └─testdata # 测试环境的数据
│ searKey.xlsx
│
├─public 公共的文件库
│ │ __init__.py
│ │
│ ├─common 封装的公共方法
│ │ │ basepage.py
│ │ │ datainfo.py
│ │ │ log.py
│ │ │ mytest.py
│ │ │ publicfunction.py
│ │ │ pyselenium.py
│ │ │ pyselenium20161107.py
│ │ │ readconfig.py
│ │ │ sendmail.py
│ │ │ __init__.py
│ │ │
│ │
│ ├─pages 使用pageobject模式编写测试脚本,存放page的目录
│ │ │ baiduIndexPage.py
│ │ │ __init__.py
│
├─report 测试报告
│ ├─image 截图目录
│ ├─log 日志目录
│ │ 2016-11-07.log
│ │
│ └─testreport html测试报告目录
│ TestResult2016-11-07_16_15_51.html
│
└─testcase 存放测试用例
│ test_baidu.py
使用说明:
安装响应的库: pip install xlrd,selenium,configparser
1、在config.ini中配置项目路径:project_path
2、测试数据放在data目录下面
3、使用pageobject,写page页面,在测试用例里面调用放在public/pages目录下
4、在testcase目录下面,编写测试用例,可以分模块编写,建相应的目录
5、执行run.py,就可以执行所有的测试用例
6、在report/log里面查看日志
7、在report/testreport里面查看html测试报告
关于pyselenium的使用:
该py文件是根据虫师的pyse改的,加了一个日志,根据自己的需要加了几个函数
可以参考虫师的pyse,github地址:https://github.com/defnngj/pyse
虫师的博客园地址:https://github.com/defnngj/pyse
导入PySlenium文件
import PySelenium
1、启动浏览器:
启动谷歌浏览器
dr = PySelenium.PySelenium('chrom')
启动远程浏览器比如使用grid施行分布式执行
dr = PySelenium.PySelenium(RChrome','127.0.0.1:8080')
2、在地址栏输入网址:
dr.open('http://www.baidu.com')
3、窗口最大化
dr.max_window()
4、设置浏览器的窗口的大小
dr.set_window(800,500)
5、不清除文本框的内容直接输入值(比如说:进行文件上传时,上传文件的路径,如果清除就会报错):
dr.type('id->su','小石头tester')
6、先清除文本框的内容,然后再输入值(用得很多):
dr.clear_type('name->su','虫师')
7、直接点击元素
dr.click('css->#kw')
8、右键点击元素:
dr.right_click('id->kw')
9、将鼠标移动到一个元素上
dr.move_to_element('clas->btn1.btn-green.btn-search')
10、双击元素
dr.double_click("id->kw")
11、将一个元素拖拽到另外一个元素上
dr.drag_and_drop('id->kw1','id->kw2')
12、根据连接的text来点击(<a href="http://www.baidu.com">百度</a>)
dr.click_text('百度')
13、关闭窗口,driver
dr.quit()
14、执行js脚本
dr.js('script')
15、获取元素的属性
dr.get_attribute("id->su","href")
16、获取元素的文本信息text
dr.get_text('id->su')
17、返回当前页面的title
dr.get_title()
18、返回当前页面的url
dr.get_url()
20、进入frame
dr.switch_to_frame('id->kw')
21、退出frame
dr.switch_to_frame_out()
22、判断元素是否存在
dr.element_exist('id->kw')
23、截图
dr.take_screenshot('file_path')
24、进入最新的table
dr.into_new_window()
25、输入内容并且回车
dr.type_and_enter('id->kw')
26、使用js来点击某个元素
dr.js_click('id->kw')
27、返回原生的webdriver,进行个性化需求
dr.origin_driver()
--------------------------------------------------------------------------------
/report/log/2016-11-08.log:
--------------------------------------------------------------------------------
1 | 2016-11-08 11:17:14,346 - root - INFO - ############################### START ###############################
2 | 2016-11-08 11:17:15,233 - root - INFO - SUCCESS Start a new browser: chrome, Spend 0.8860507011413574 seconds
3 | 2016-11-08 11:17:16,335 - root - INFO - SUCCESS Set browser window maximized, Spend 1.0990626811981201 seconds
4 | 2016-11-08 11:17:18,290 - root - INFO - SUCCESS Navigated to http://www.baidu.com, Spend 1.9541118144989014 seconds
5 | 2016-11-08 11:17:18,395 - root - INFO - SUCCESS Clear and type element: kw> content: 小石头tester, Spend 0.10500597953796387 seconds
6 | 2016-11-08 11:17:18,474 - root - INFO - SUCCESS Clicked element: su>, Spend 0.07900476455688477 seconds
7 | 2016-11-08 11:17:20,491 - root - INFO - SUCCESS Get current window title, Spend 0.014000654220581055 seconds
8 | 2016-11-08 11:17:21,731 - root - INFO - SUCCESS Closed all window and quit the driver, Spend 1.2390711307525635 seconds
9 | 2016-11-08 11:17:21,733 - root - INFO - ############################### End ###############################
10 | 2016-11-08 11:17:21,735 - root - INFO - ############################### START ###############################
11 | 2016-11-08 11:17:22,653 - root - INFO - SUCCESS Start a new browser: chrome, Spend 0.9170525074005127 seconds
12 | 2016-11-08 11:17:23,621 - root - INFO - SUCCESS Set browser window maximized, Spend 0.967055082321167 seconds
13 | 2016-11-08 11:17:25,663 - root - INFO - SUCCESS Navigated to http://www.baidu.com, Spend 2.032116174697876 seconds
14 | 2016-11-08 11:17:25,770 - root - INFO - SUCCESS Clear and type element: kw> content: webdriver, Spend 0.10600590705871582 seconds
15 | 2016-11-08 11:17:25,946 - root - INFO - SUCCESS Clicked element: su>, Spend 0.1760101318359375 seconds
16 | 2016-11-08 11:17:27,962 - root - INFO - SUCCESS Get current window title, Spend 0.014000892639160156 seconds
17 | 2016-11-08 11:17:28,313 - root - INFO - SUCCESS Navigated to http://www.baidu.com, Spend 0.3500199317932129 seconds
18 | 2016-11-08 11:17:28,398 - root - INFO - SUCCESS Clear and type element: kw> content: selenium, Spend 0.08300471305847168 seconds
19 | 2016-11-08 11:17:28,506 - root - INFO - SUCCESS Clicked element: su>, Spend 0.10800623893737793 seconds
20 | 2016-11-08 11:17:30,520 - root - INFO - SUCCESS Get current window title, Spend 0.012000799179077148 seconds
21 | 2016-11-08 11:17:30,865 - root - INFO - SUCCESS Navigated to http://www.baidu.com, Spend 0.34201955795288086 seconds
22 | 2016-11-08 11:17:30,948 - root - INFO - SUCCESS Clear and type element: kw> content: github, Spend 0.08000469207763672 seconds
23 | 2016-11-08 11:17:31,047 - root - INFO - SUCCESS Clicked element: su>, Spend 0.09800577163696289 seconds
24 | 2016-11-08 11:17:33,059 - root - INFO - SUCCESS Get current window title, Spend 0.010000467300415039 seconds
25 | 2016-11-08 11:17:33,365 - root - INFO - SUCCESS Navigated to http://www.baidu.com, Spend 0.3040175437927246 seconds
26 | 2016-11-08 11:17:33,451 - root - INFO - SUCCESS Clear and type element: kw> content: 小石头tester, Spend 0.08500480651855469 seconds
27 | 2016-11-08 11:17:33,556 - root - INFO - SUCCESS Clicked element: su>, Spend 0.10500597953796387 seconds
28 | 2016-11-08 11:17:35,569 - root - INFO - SUCCESS Get current window title, Spend 0.012000799179077148 seconds
29 | 2016-11-08 11:17:36,845 - root - INFO - SUCCESS Closed all window and quit the driver, Spend 1.2740728855133057 seconds
30 | 2016-11-08 11:17:36,847 - root - INFO - ############################### End ###############################
31 | 2016-11-08 11:17:43,322 - root - INFO - 发送邮件成功
32 |
--------------------------------------------------------------------------------
/report/testreport/TestResult2016-11-08_11_17_14.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 测试报告
6 |
7 |
8 |
9 |
10 |
11 |
94 |
95 |
96 |
97 |
191 |
192 |
193 |
测试报告
194 |
Start Time: 2016-11-08 11:17:14
195 |
Duration: 0:00:22.500287
196 |
Status: Pass 2
197 |
198 |
Test the import testcase
199 |
200 |
201 |
202 |
203 | Show
204 | Summary
205 | Failed
206 | All
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
225 |
226 |
227 | test_baidu.TestBaiduIndex: 百度搜索测试 |
228 | 2 |
229 | 2 |
230 | 0 |
231 | 0 |
232 | Detail |
233 |
234 |
235 |
236 | test_search: 直接搜索 |
237 |
238 |
239 |
240 |
242 |
243 |
264 |
265 |
266 | |
267 |
268 |
269 |
270 | test_search_excel: 使用数据驱动,进行测试 |
271 |
272 |
273 |
274 |
276 |
277 |
310 |
311 |
312 | |
313 |
314 |
315 |
316 | Total |
317 | 2 |
318 | 2 |
319 | 0 |
320 | 0 |
321 | |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
--------------------------------------------------------------------------------
/run.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | import unittest
4 | import HTMLTestRunner
5 | import time
6 | from config import globalparam
7 | from public.common import sendmail
8 |
9 | def run():
10 | test_dir = './testcase'
11 | suite = unittest.defaultTestLoader.discover(start_dir=test_dir,pattern='test*.py')
12 |
13 | now = time.strftime('%Y-%m-%d_%H_%M_%S')
14 | reportname = globalparam.report_path + '\\' + 'TestResult' + now + '.html'
15 | with open(reportname,'wb') as f:
16 | runner = HTMLTestRunner.HTMLTestRunner(
17 | stream=f,
18 | title='测试报告',
19 | description='Test the import testcase'
20 | )
21 | runner.run(suite)
22 | time.sleep(3)
23 | # 发送邮件
24 | mail = sendmail.SendMail()
25 | mail.send()
26 |
27 | if __name__=='__main__':
28 | run()
--------------------------------------------------------------------------------
/testcase/__pycache__/test_baidu.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xiaoshitoutester/UItestframework/b8d3125ed8ffacfd77fc271c6bf1e7105035c0c9/testcase/__pycache__/test_baidu.cpython-35.pyc
--------------------------------------------------------------------------------
/testcase/test_baidu.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | from time import sleep
4 | from public.common import mytest
5 | from public.pages import baiduIndexPage
6 | from public.common import datainfo
7 |
8 |
9 | class TestBaiduIndex(mytest.MyTest):
10 | """百度搜索测试"""
11 |
12 | def _search(self,searchKey):
13 | """封装百度搜索的函数"""
14 | baidupage = baiduIndexPage.BaiduIndexPage(self.dr)
15 | baidupage.into_baidu_page()
16 | baidupage.input_search_key(searchKey)
17 | baidupage.click_search_button()
18 | sleep(2)
19 | self.assertIn(searchKey, baidupage.return_title())
20 |
21 | def test_search(self):
22 | """直接搜索"""
23 | baidupage = baiduIndexPage.BaiduIndexPage(self.dr)
24 | baidupage.into_baidu_page()
25 | baidupage.input_search_key('小石头tester')
26 | baidupage.click_search_button()
27 | sleep(2)
28 | self.assertIn('小石头',baidupage.return_title())
29 |
30 | def test_search_excel(self):
31 | """使用数据驱动,进行测试"""
32 | datas = datainfo.get_xls_to_list('searKey.xlsx','Sheet1')
33 | for data in datas:
34 | self._search(data)
35 |
36 |
--------------------------------------------------------------------------------