Initial commit

This commit is contained in:
floraachy 2020-03-12 17:12:39 +08:00
commit a7ce0026f3
86 changed files with 97557 additions and 0 deletions

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
.cache/
__pycache__/
*.pyc
/chrometest.py
/demo.py
/run.py
/.idea/
/venv/
framework/__pycache__/
pom/__pycache__/
pom/elements/__pycache__/
pom/pages/__pycache__/
screenshots/
testcase/__pycache__/
/report/html/*.html
/report/logs/*.log

View File

@ -0,0 +1,104 @@
=================================
HomeWork
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
一、下面那些不能作为变量?
1、find 2、 _num 3、7val 4、add. 5、def
6、pan 7、-print 8、open_file 9、FileName 10、9prints
11、INPUT 12、ls 13、user^name 14、list1 15、str_
16、_888 17、is 18、true 19、none 20、try
答: 不能作为变量的是7val, add., def, -print, 9prints, user^name, is, try
二、请描述一下变量的命名规范,(简单题)
变量名命名的规范:
变量只能包含字母、数字和下划线
变量名可以字母或下划线开头,不能以数字开头
变量名不能包含空格,但可以使用下划线来分隔其中的单词
不能将python关键字和函数名作为变量名
变量名应该见名知意
三、python如何如何添加注释
单行注释用井号(#)标识
多行注释用三引号(""")标识
四、把学的python基本语法总结成笔记以后每次课都要整理
=======================================================
python的基本语法
-------------------------------------------------------
输出函数print
示例print("hello world!")
输入函数input 控制台输入内容
示例input("请输入:")
打印python关键字35个python内置的一些具有特定功能的单词
import keyword
print(keyword.kwlist)
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
注释:
单行注释用井号(#标识快捷键Ctrl+/ 注释是不会换行的
多行注释(文档注释/文档字符型串)用三引号(""" )标识 对整个文件的内容进行相关的注释说明
注意:注释的目的是阐述代码要做什么,以及如何做
变量名命名的规范:
变量只能包含字母、数字和下划线
变量名可以字母或下划线开头,不能以数字开头
变量名不能包含空格,但可以使用下划线来分隔其中的单词
不能将python关键字和函数名作为变量名
变量名应该见名知意(不推荐使用拼音)
变量名命名的风格:
下划线命名推荐如果变量由多个单词组成单词之间用下划线连接如name_max
小驼峰命名不推荐如果变量由多个单词组成第二个单词开始首字母大写如nameMin
大驼峰命名(不推荐):如果变量由多个单词组成, 每个单词首字母大写如NameMax
扩展:
常量命名:纯大写字母(推荐) 常量是不变的,如圆周率
标识符:
凡是我们自己取得名字都是标识符
标识符包括变量名,函数名,类名,文件名(模块名),项目名
数值:
整数如a = 100
小数(浮点数), 如b = 3.44
字符串:引号引起来的一串文字
示例str = 'hello'
=======================================================

View File

@ -0,0 +1,66 @@
=================================
HomeWork
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******Python中常见的数据类型******
数值类型数据:
1. 整数(int)例如a = 100
2. 小数(float)(浮点数), 例如 b = 2.3
3. 布尔值(bool: True, False) 例如c= True, d = False
内置函数type():可以用来查看数据的类型
******Python中的运算符******
1. 算术运算符: + - * / //(向下取整) %(取余) **(幂运算)
2. 比较运算符:== != > >= < <= 返回的是True或False
3. 赋值运算符:= += -= *= /= *=
示例: a += 1 相当于a = a + 1
4. 逻辑运算符(用来比较2个条件)and(与) or(或) not(非) 返回的是True或False
and所有条件都成立返回True否则返回False。一假为假 真真为真。
or只要有一个条件成立返回True条件都不成立返回False。一真为真假假为假。
not 取反。原来是True返回False; 原来是False返回True。
5. 身份运算符(后面学)
6. 成员运算符(后面学)
******python中的内置随机函数random******
random.random()随机生成一个0-1之间的浮点数生成的小数范围是左闭右开包含0不包含1。
random.randint():生成指定范围的整数;包含起始位置和终止位置的值。
random.uniform():生成指定范围的浮点数;闭区间或者左闭右开。
import random
number = random.random()
number1 = random.randint(0, 100)
******字符串类型*****
1. 字符串可以通过单引号,双引号,三引号来表示。
2. 单引号和双引号没有区别。
3. 三引号可以用来表示多行字符串。
示例:
str1 = '单引号'
str2 = "双引号"
str3 = """三双引号"""
str3 = '''三单引号
三单引号
'''
******数据类型转换*****
整数和浮点数转换为字符串使用str
字符串和浮点数转换为整数使用int
整数和字符串转换为浮点数使用float
整数和浮点数字符串转换为布尔类型bool
注意点:
使用字符串转换为int或float时字符串的内容必须是数字不能有字母和符号
整数和浮点数转布尔值只要不是0返回的布尔值都是True否则是False。
字符串转布尔值,空字符串(引号中没有任何内容,包括空格或者其他标点符号)返回的布尔值是False其他都是True。
扩展:
按编码规范格式化代码的快捷键(pycharm)Ctrl + Alt + L

View File

@ -0,0 +1,202 @@
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******字符串拼接******
1. 通过+对字符串进行拼接
示例:
str1 = 'python'
str2 = 'hello'
print(str1 + str2) # 输出结果pythonhello
# 此种方法输出会在中间加空格
print(str1, str2) # 输出结果python hello
2. 使用字符串的join方法进行拼接
示例:
str1 = 'python'
str2 = 'hello'
j = '---'
str3 = j.join((str1, str2))
print(str3) # 输出结果python---hello
或者
str1 = 'python'
str2 = 'hello'
str3 = ' '.join((str1, str2))
print(str3) # 输出结果python hello
或者
str1 = 'python'
str2 = ' '.join(str1)
print(str2) # 输出结果p y t h o n
******字符串格式化输出******
1. format格式化输出常用方式必须掌握
示例:
str1 = '今天收到{} 交来{}{}。开此收据为凭证。'
str2 = str1.format('flora', '学杂费', 666)
print(str2) # 输出结果: 今天收到flora 交来学杂费666。开此收据为凭证。
或:
print('今天收到{} 交来{}{}。开此收据为凭证。'.format('flora', '学杂费', 666))
通过索引来控制填充的位置:
name = input('请输入名字:')
info = input('请输入费用信息:')
money = input('请输入金额:')
print('今天收到{2} 交来{1}费用{0}。开此收据为凭证。'.format(money, info, name))
保留指定小数位数:
name = input('请输入名字:')
info = input('请输入费用信息:')
money = float(input('请输入金额:'))
print('今天收到{} 交来{}费用${:.2f}。开此收据为凭证。'.format(name, info, money))
指定占位的字符串长度:
# 默认左对齐
print('python:{:10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果python:123 AAAAAAAAAAAAAAA
# 左对齐
print('python:{:<10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果python:123 AAAAAAAAAAAAAAA
# 右对齐
print('python:{:>10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果python: 123AAAAAAAAAAAAAAA
# 居中对齐
print('python:{:^10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果python: 123 AAAAAAAAAAAAAAA
指定内容填充:
# 左对齐,以*填充
print('python:{:*<10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果123*******AAAAAAAAAAAAAAA
# 右对齐,以-填充
print('python:{:->10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果:-------123AAAAAAAAAAAAAAA
# 居中对齐,以@填充
print('python:{:@^10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果:@@@123@@@@AAAAAAAAAAAAAAA
百分比显示效果:
print('百分比:{:.2%}'.format(0.89))
# 输出结果百分比89.00%
2. 传统的%格式化输出
%s万能占位符可以接收任意类型的数据。
%d数值占位符以整数的形式显示。
%f: 数值占位符,以小数的形式显示。
示例:
print('今天收到%s 交来%s%d。开此收据为凭证。' % ('flora', '学杂费', 666.98))
# 输出结果: 今天收到flora 交来学杂费666。开此收据为凭证。
print('今天收到%s 交来%s%f。开此收据为凭证。' % ('flora', '学杂费', 666))
# 输出结果: 今天收到flora 交来学杂费666.000000。开此收据为凭证。
print('今天收到%s 交来%s%.2f。开此收据为凭证。' % ('flora', '学杂费', 666.909090))
# 输出结果今天收到flora 交来学杂费666.91。开此收据为凭证。
3. F表达式格式化输出
示例:
name = input('请输入名字:')
info = input('请输入费用信息:')
money = input('请输入金额:')
print(F'今天收到{name} 交来{info}{money}。开此收据为凭证。')
******字符串转义******
反斜杠\表示转义
\t制表符tab键
\n换行符
\\表示1个反斜杠\
示例:
print('python\thello')
# 输出结果python hello
print('python2\nhello2')
# 输出结果:
python2
hello2
关闭字符串转义r防转义
print(r'python\thello')
# 输出结果python\thello
print(r'python2\nhello2')
# 输出结果python2\nhello2
******字符串的常见操作方法******
1. count查找字符串中某个字符串的个数
示例:
print('123aa123bb123cc123dd'.count('123'))
# 输出结果4
2. find查找字符串中某个字符串出现的第一个下标索引位置
示例:
print('123aa123bb123cc123dd'.find('aa'))
# 输出结果3
3. replace替换字符串中的某个字符串默认替换所有
示例:
print('123aa123bb123cc123dd'.replace('123', '*'))
# 输出结果:*aa*bb*cc*dd
# 可控制替换的次数
print('123aa123bb123cc123dd'.replace('123', '*', 1))
# 输出结果:*aa123bb123cc123dd
4. upper将字符串中的小写字母变成大写字母
示例:
print('Hello World 132'.upper())
# 输出结果HELLO WORLD 132
5. lower将字符串中的大写字母变成小写字母
示例:
print('Hello World 132'.lower())
# 输出结果hello world 132
6. split字符串分割
示例:
# 以空格方式进行分割,返回的是个列表
print('Hello World 132'.split(' '))
# 输出结果:['Hello', 'World', '132']
# 使用join方法反向操作
print(' '.join(['Hello', 'World', '132']))
# 输出结果Hello World 132
******元组和列表******
列表和元组中可以保存多个数据,可以是任意类型的,每个元素之间用逗号隔开。
元组tuple 用小括号来表示
tup = ('python', 66, 88.88, True, [11, 22, 33])
列表list 用中括号来表示
li = ['python', 66, 88.88, True, [11, 22, 33]]
扩展:
序列类型的数据:数据内部的元素是由顺序的(有下标)
序列类型的数据:字符串,列表,元组
序列类型数据的共同特性:
1. 可以通过下标取值:通过下标获取数据内的元素
示例:
# 正向取值从前往后数下标下标从0开始
print('python'[2]) # 输出结果t
print(['python', 66, 88.88, True, [11, 22, 33]][1]) # 输出结果66
print(('python', 66, 88.88, True, [11, 22, 33])[0]) # 输出结果python
# 反向取值:从后往前数下标,下标从-1开始
print('python'[-2]) # 输出结果o
print(['python', 66, 88.88, True, [11, 22, 33]][-1]) # 输出结果:[11, 22, 33]
print(('python', 66, 88.88, True, [11, 22, 33])[-3]) # 输出结果88.88
2. 可以通过切片操作:获取数据中某一段数据,[起始位置:终止位置] 左闭右开
示例:
li = ['python', 66, 88.88, True, [11, 22, 33]]
print('[起始位置:终止位置] 左闭右开:', li[0:3])
# 输出结果:[起始位置:终止位置] 左闭右开: ['python', 66, 88.88]

View File

@ -0,0 +1,211 @@
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******列表切片******
可以通过切片操作:获取数据中某一段数据
用法一: [起始位置:终止位置] 左闭右开
示例:
li = ['python', 66, 88.88, True, [11, 22, 33]]
print('[起始位置:终止位置] 左闭右开:', li[0:3])
# 输出结果:[起始位置:终止位置] 左闭右开: ['python', 66, 88.88]
# 使用反向的下标进行切片
print(li[-2:-1]) # 输出结果:[True]
# 正向和反向下标可以混用
print(li[1:-2]) # 输出结果:[66, 88.88]
用法二:[起始位置:终止位置:步长]
1. 步长为正数
示例:
li = ['python', 66, 88.88, True, [11, 22, 33]]
# 默认步长为1默认打印整个列表
print(li[::]) # 输出结果: ['python', 66, 88.88, True, [11, 22, 33]]
# 步长为2 2个元素中取第一个元素。所以是1 3 5
print(li[::2]) # 输出结果: ['python', 88.88, [11, 22, 33]]
# 步长为3 3个元素中取第一个元素。所以是1 4
print(li[::3]) # 输出结果: ['python', True]
# 步长为4 4个元素中取第一个元素。所以是1 5
print(li[::4]) # 输出结果: ['python', [11, 22, 33]]
2. 步长设置为负数
示例:
li = ['python', 66, 88.88, True, [11, 22, 33]]
# 步长为-1 是从后往前切片
print(li[::-1]) # 输出结果:[[11, 22, 33], True, 88.88, 66, 'python']
print(li[-1:-4:-1]) # 输出结果:[[11, 22, 33], True, 88.88]
******列表的常见操作方法******
列表list 用中括号[]来表示
列表可以保存多个数据,可以是任意类型的,每个元素之间用逗号隔开。
列表可以转换成布尔值空列表li = []的布尔值为False其他的布尔值都是True。
1. 内置函数len获取字符串列表元组字典集合的长度
示例:
li = ['python', 66, 88.88, True, [11, 22, 33]]
print(len(li)) # 输出结果5
2. 新增列表元素
append(): 在列表尾部追加元素
示例:
li = ['nancy', 'lily']
li.append('flora')
print(li) # 输出结果:['nancy', 'lily', 'flora']
insert(需要添加元素的下标位置, 需要添加的元素):指定位置添加元素
示例:
li = ['nancy', 'lily', 'flora']
li.insert(1, 'robot')
print(li) # 输出结果:['nancy', 'robot', 'lily', 'flora']
extend():一次性在列表尾部添加多个元素。注意:必须将需要添加的多个元素放在列表或者元组里面。
示例:
li = ['nancy', 'lily', 'flora']
li.extend(['jane', 'robot', 1, 2])
print(li) # 输出结果:['nancy', 'lily', 'flora', 'jane', 'robot', 1, 2]
3. 删除列表元素
remove(元素值):删除列表指定的元素
示例:
li = ['nancy', 'lily', 'flora']
li.remove('lily')
print(li) # 输出结果:['nancy', 'flora']
pop():通过下标删除指定的元素,默认删除最后一个
示例:
li = ['nancy', 'lily', 'flora', 'robot', 'jane']
li.pop()
print(li) # 输出结果:['nancy', 'lily', 'flora', 'robot']
li.pop(1)
print(li) # 输出结果:['nancy', 'flora', 'robot']
clear():清空列表(删除列表中的所有元素)
示例:
li = ['nancy', 'lily', 'flora', 'robot', 'jane']
li.clear()
print(li) # 输出结果:[]
4. 查看列表元素
通过下标取值
示例:
li = ['nancy', 'lily', 'flora', 'robot', 'jane']
# 通过下标取值查找元素
print(li[1]) # 输出结果lily
index():查找元素的下标值(找到第一个就返回,不会继续再查找;如果元素不存在会报错。)
示例:
li = ['nancy', 'lily', 'flora', 'robot', 'jane', 'flora', 'miya', 'apple']
index = li.index('flora')
print(index) # 输出结果2
# 在指定范围内查找元素的下标值,左闭右开
index = li.index('flora', 3, 6)
print(index) # 输出结果5
count():查找列表中某个元素的个数
示例:
li = ['nancy', 'lily', 'flora', 'robot', 'jane', 'flora', 'miya', 'apple']
print(li.count('flora')) # 输出结果2
5. 修改列表元素
通过下标赋值
示例:
li = ['nancy', 'lily', 'flora', 'robot', 'jane', 'flora', 'miya', 'apple']
li[1] = 11
print(li) # 输出结果:['nancy', 11, 'flora', 'robot', 'jane', 'flora', 'miya', 'apple']
6. 列表的其他方法
sort()对列表进行排序列表中全是数值类型如果列表中全是字符串是按照ASCII值进行排序的。
示例:
li = [11, 2, 353, 44, 88, 99, 123]
li.sort() # 默认从小到大排序, reverse默认为False
print(li) # 输出结果:[2, 11, 44, 88, 99, 123, 353]
li.sort(reverse=True) # 从大到小排序
print(li) # 输出结果:[353, 123, 99, 88, 44, 11, 2]
reverse():将列表反向,从末尾到起始排序
示例:
li = [11, 2, 353, 44, 88, 99, 123]
li.reverse() # 此操作相当于 li[::-1]
print(li) # 输出结果:[123, 99, 88, 44, 353, 2, 11]
copy():复制
示例:
li = [1, 2, 3, 4, 5, 6, 7]
# 变量赋值引用的是li中的数据
li2 = li
print(id(li)) # 输出结果2144668143360
print(id(li2)) # 输出结果2144668143360
# 在列表类li2中追加元素同样会作用到li中
li2.append(9)
print(li) # 输出结果:[1, 2, 3, 4, 5, 6, 7, 9]
print(li2) # 输出结果:[1, 2, 3, 4, 5, 6, 7, 9]
# 复制
li3 = li.copy()
print(id(li3)) # 输出结果2814574980480
print(li is li3) # 输出结果False
# 在列表类li3中追加元素不会影响li
li3.append(80)
print(li) # 输出结果:[1, 2, 3, 4, 5, 6, 7, 9]
print(li3) # 输出结果:[1, 2, 3, 4, 5, 6, 7, 9, 80]
******运算符补充******
身份运算符is, is not比较2个数据是否引用的是同一个对象比较id内存地址是否一致
示例:
li = [11, 2, 353, 44]
li2 = [11, 2, 353, 44]
li3 = li
# 内置函数id查看数据的内存地址
print(id(li)) # 输出结果1792807521984
print(id(li2)) # 输出结果1792807540928
print(id(li3)) # 输出结果1792807521984
print(li is li2) # 输出结果False
print(li is li3) # 输出结果True
print(li is not li3) # 输出结果False
扩展:
在python中 -5 到 256 之间的数据(小整数池),内存地址都是一样的。
# 在终端运行
a = -5
b = -5
print(id(a)) # 输出结果140706950989280
print(id(b)) # 输出结果140706950989280
a = -6
b = -6
print(id(a)) # 输出结果1739394026288
print(id(b)) # 输出结果1739394026352
成员运算符in, not in判断某个元素是否存在于列表中
示例:
li = [1, 2, 3, 4, 5, 6, 7]
zs = 1
ls = 8
# 判断zs, ls是否存在于列表中
print(zs in li) # 输出结果True
print(ls in li) # 输出结果False
# 判断zs, ls是否不存在于列表中
print(zs not in li) # 输出结果False
print(ls not in li) # 输出结果True
******元组******
元组tuple 用小括号来表示
元组的方法只有查询的方法。没有添加元素,修改元素,删除元素的方法。
1. 通过下标取值
index():查找元素的下标值(找到第一个就返回,不会继续再查找;如果元素不存在会报错。)
示例:
tup = (1, 2, 33, 4, 5, 6, 33, 44, 33, 7)
print(tup[2]) # 输出结果33
print(tup.index(33)) # 输出结果2
print(tup.index(33, 3, 8)) # 输出结果6
2. count():查找列表中某个元素的个数
示例:
tup = (1, 2, 33, 4, 5, 6, 33, 44, 33, 7)
print(tup.count(33)) # 输出结果3

View File

@ -0,0 +1,111 @@
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******字典dict******
1. 字典的定义
花括号{}表示字典,字典中的元素是由键值(key:value)对组成的,每个元素用逗号隔开。
字典是没有下标索引的其键key就是索引。
第一种:直接通过{'key': value}的形式定义
dic = {'a': 11, 'b': 12}
第二种使用dict()转换[('key', value), ('key', value) ...]这种数据类型
dic = dict([('a', 11), ('b', 12)])
第三种dict(key = value, key = value ...)
dic = dict(a=11, b=12)
示例:
dic = {}
dict2 = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
print(type(dic)) # 输出结果:<class 'dict'>
print(dict2) # 输出结果:{'name': 'flora', 'age': 18, 'phone': '10220020200'}
print(dict2['name']) # 输出结果flora
2. 字典中的相关规范
字典中的键不能重复。
字典中的键只能使用不可变类型(字符串,数值类型,元组)的数据(通常是用字符串)。
字典中的值可以是任何数据类型。
扩展:
不可变类型的数据:数值类型,字符串,元组
可变类型的数据:列表,字典,集合
3. 字典的相关操作
添加一个元素
示例:
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
dic['height'] = 156
print(dic)
# 输出结果:{'name': 'flora', 'age': 18, 'phone': '10220020200', 'height': 156}
添加多个元素
示例:
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
dic.update({'height': 156, 'heavy': '56kg'})
print(dic)
# 输出结果:{'name': 'flora', 'age': 18, 'phone': '10220020200', 'height': 156, 'heavy': '56kg'}
修改元素:键已存在就是修改。否则是新增。
示例:
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
dic['phone'] = '18956423668'
print(dic)
# 输出结果:{'name': 'flora', 'age': 18, 'phone': '18956423668'}
删除元素
pop():通过键去删除指定的键值对,返回键对应的值
示例:
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
res = dic.pop('phone')
print(res) # 输出结果10220020200
print(dic)
# 输出结果:{'name': 'flora', 'age': 18}
popitem():删除最后添加进去的键值对,以元组的形式返回一个键值对
示例:
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
res = dic.popitem()
print(res) # 输出结果:('phone', '10220020200')
print(dic)
# 输出结果:{'name': 'flora', 'age': 18}
查找元素
通过键进行索引取值,键不存在会报错
示例:
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
res = dic['phone']
print(res) # 输出结果10220020200
get()通过键获取对应的值键不存在不会报错但是会返回None
示例:
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
res = dic.get('phone')
print(res) # 输出结果10220020200
res2 = dic.get('heg') #键不存在
print(res2) # 输出结果None
获取字典中的所有键,所有值,所有键值对
keys():获取字典中所有的键
示例:
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
print(dic.keys()) # 输出结果dict_keys(['name', 'age', 'phone'])
print(list(dic.keys())) # 可通过list()转换成列表
# 输出结果:['name', 'age', 'phone']
values():获取字典中所有的值
示例:
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
print(dic.values()) # 输出结果dict_values(['flora', 18, '10220020200'])
print(list(dic.values())) # 可通过list()转换成列表
# 输出结果:['flora', 18, '10220020200']
items():获取字典中所有的键值对
示例:
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
print(dic.items()) # 输出结果dict_items([('name', 'flora'), ('age', 18), ('phone', '10220020200')])
print(list(dic.items())) # 可通过list()转换成列表
# 输出结果:[('name', 'flora'), ('age', 18), ('phone', '10220020200')]

View File

@ -0,0 +1,231 @@
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******集合******
1. 集合的定义
集合: set类型 通过{}来表示
内部的数据{value, value1, value2}
示例:
set1 = {11, 22, 33, 44, 55}
print(type(set1)) # 输出结果:<class 'set'>
2. 集合的特性
集合的数据不能存在重复的元素;
集合中的数据只能是不可变类型(数值类型,字符串,元组);
集合和字典都是无序的,没有下标索引;
集合是可变类型的数据。
集合的操作:
add: 添加数据
pop删除数据
示例:
set1 = {11, 22, 33, 44, 55, 55}
print(set1) # 输出结果:{33, 11, 44, 22, 55}
set1.add(678)
print(set1) # 输出结果:{33, 678, 11, 44, 22, 55}
set1.pop() # 随机删除一个元素
print(set1) # 输出结果:{678, 11, 44, 22, 55}
3. 集合的应用
对数据的去重
示例:
# 对字符串去重
str1 = 'dfgdfghjkhjk'
s1 =set(str1)
print(s1) # 输出结果:{'d', 'k', 'f', 'j', 'g', 'h'}
# 对列表去重
li = [11, 11, 22, 22, 33]
s1 =set(li)
print(list(s1)) # 输出结果:[33, 11, 22]
用来区分数据是否可变
# 运行不报错的就都是不可变类型的:数值类型,字符串,元组
set1 = {111, 12.33, '243', True, (1, 2)}
# 运行报错的就都是可变类型的:列表,字典,集合
# set2 = {[1, 2, 3]} # TypeError: unhashable type: 'list'
# set3 = {{'name': 'flora'}} # TypeError: unhashable type: 'dict'
set4 = {{1,2,3}} # TypeError: unhashable type: 'set'
******数据类型总结******
1. 按数据结构分类
数值类型:整数,浮点数,布尔值
序列类型:字符串,列表,元组(可以通过下标取值,支持切片操作)
散列类型:字典,集合(元素内部是无序的,没有下标)
2. 数据类型的可变与不可变
不可变类型:数值类型,字符串,元组
字符串和元组定义之后不能修改内部结构或者值(内存单元中的值),为不可变类型
可变类型:列表,字典,集合
如何区分可变不可变数据:定义一个集合,把数据放到集合中看会不会报错。会报错的是可变类型。
******控制流******
顺序:代码从上往下执行
分支:根据不同的条件,执行不同的代码
循环:特定的代码重复执行
注意python中通过缩进来区分代码块的。
******条件判断******
1. if语句
if 条件:
# 条件成立执行的代码块
示例:
# 用户输入考试成绩,请判断是否及格。
score = float(input('请输入您的成绩:'))
if score >= 60:
# 条件成立执行的代码块
print('考试及格!')
2. if - else语句
if 条件:
# 条件成立执行的代码块
else:
# 条件不成立执行的代码块
示例:
# 用户输入考试成绩,请判断是否及格。如果考试不及格,打印:考试不及格,晚上通宵敲代码!
score = float(input('请输入您的成绩:'))
if score >= 60:
# 条件成立执行的代码块
print('考试及格!')
else:
# 条件不成立执行的代码块
print('考试不及格,晚上通宵敲代码!')
3. if - elif - else语句
if 条件1
# 条件成立执行的代码块
elif 条件2
# 条件2成立执行的代码块
elif 条件3
# 条件3成立执行的代码块
else:
# 以上条件均不成立执行的代码块
# 用户输入考试成绩根据不同等级进行区分A 90分以上 B80-90分 C 60-80分 D60分以下
score = int(input('请输入您的成绩:'))
if 0 <= score < 60:
print('您的成绩为D')
elif 60 <= score < 80:
print('您的成绩为C')
elif 80 <= score < 90:
print('您的成绩为B')
elif 90 <= score < 100:
print('您的成绩为A')
else:
print('您输入的成绩有误!')
4. 多个条件同时判断
# 登录小案例:事先存储一组账号密码,提示用户输入账号和密码,然后判断账号密码是否输入正确
user_info = {'user': 'flora', 'pwd': '123455555Az'}
username = input('请输入账号:')
passwd = input('请输入密码:')
# 方式一:使用嵌套方式
if username == user_info['user']:
if passwd == user_info['pwd']:
print('账号密码输入正确!')
else:
print('密码输入不正确!')
else:
print('账号输入不正确!')
# 方式二:使用逻辑运算符去判断多个条件
if username == user_info['user'] and passwd == user_info['pwd']:
print('账号密码输入正确!登录成功!')
else:
print('账号或密码输入不正确!登录失败!')
总结:
使用if开启一个条件判断语句
一个条件语句中只有一个if但是一个条件语句中可以有多个或者一个或者零个elif;
一个条件语句中只有一个或者零个else。
if判断成立的标准
if成立的标准是根据if后面的python表达式或者数据的布尔值是否为True来确定条件是否成立
******python中数据的布尔值******
非0位TrueNone 数字0或者数据长度为0len()的布尔值为False 其他数据布尔值都是True
数据长度为0 例如:空字符串,空列表,空元祖,空字典
示例:
str1 = 'python'
li = [1, 2, 2]
if li:
print('成立!')
else:
print('不成立!')
******while循环(条件循环)******
1. while循环的使用
如果条件一直成立,则一直循环做条件满足的事情,直到条件不成立,结束循环。
while 条件:
# 条件成立,循环执行的代码块
# 条件成立,循环执行的代码块
# 条件成立,循环执行的代码块
# ......
示例:
# 创建一个变量来保存循环的次数
i = 0
while i < 5:
print('hello python')
i += 1 # i = i + 1
# 输出结果:
"""
hello python
hello python
hello python
hello python
hello python
"""
2. 死循环以及相关案例的使用
死循环:循环的条件一直成立,在循环体中无限循环,称之为死循环。
避免写代码的过程中因为逻辑问题,造成代码死循环。
示例:
while True:
print('hello python')
3. break强制跳出循环
死循环在特定的需求下我们也会使用再循环内部要实现跳出循环的机制合理使用break
示例:
while True:
user_info = {'user': 'flora', 'pwd': '123455555Az'}
username = input('请输入账号:')
passwd = input('请输入密码:')
if username == user_info['user'] and passwd == user_info['pwd']:
print('账号密码输入正确!登录成功!')
break
else:
print('账号或密码输入不正确!请重新输入!')
4. 循环内嵌套条件语句
示例:
# 打印3次之后强制退出循环
i = 0
while i < 5:
print('hello python')
i += 1 # i = i + 1
# 当i=3时退出循环
if i == 3:
break
5. continue终止本轮循环直接进行下次循环的条件判断
示例:
# 第5-7次不打印
i = 0
while i < 10:
i += 1 # i = i + 1
# 当i在5~7之间则执行continue终止本轮循环进行下轮循环的条件判断
if 5 <= i <= 7:
continue
print('hello python')

View File

@ -0,0 +1,169 @@
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******for循环******
1. 定义
for i in xxx:
# 循环体
2. 遍历字符串
示例:
str1 = 'flora'
for i in str1:
print(i)
3. 遍历列表
示例:
# 当前有10位同学的成绩在一个列表中请区分成绩的等级
li = [90, 78, 56, 89, 65, 80, 74, 34, 89, 100]
for score in li:
if 0 < score < 60:
print('成绩{}:不及格'.format(score))
elif 60 <= score < 80:
print('成绩{}:及格'.format(score))
elif 80 <= score < 90:
print('成绩{}:优秀'.format(score))
else:
print('成绩{}:非常优秀'.format(score))
4. 遍历字典
示例:
dic1 = {'name': 'flora', 'gender': 'girl', 'age': 18}
for i in dic1.keys():
print('遍历字典的键:', i)
for i in dic1.values():
print('遍历字典的值:', i)
for i in dic1.items():
print('遍历字典的键值对:', i)
# 遍历字典键值对时用2个变量分别保存键和值。
# for i in dic1.items():
# k, v = i
# print('遍历字典的键:', k)
# print('遍历字典的值:', v)
for k, v in dic1.items():
print('遍历字典的键:', k)
print('遍历字典的值:', v)
5. for循环中的break, continue
示例:
# 需求一打印10遍hello python
for i in range(1, 11):
print('1: 这是第{}遍: hello python'.format(i))
# 需求二打印到第50遍跳出循环
for i in range(1, 11):
print('2: 这是第{}遍: hello python'.format(i))
if i == 5:
break
# 需求三第3~5遍不打印
for i in range(1, 11):
if 3 <= i <= 5:
continue
print('3这是第{}遍: hello python'.format(i))
6. for循环中的高级语法for -- else
for对应的else语句只有当循环是通过break结束的时候不会执行。其他情况下都会执行。
示例:
for i in range(10):
print('本轮遍历的数据为{}'.format(i))
else:
print('for对应的else语句')
示例:
users = [{'user': 123}, {'user': 122}, {'user': 124}]
user = input('请输入您的账号:')
for i in users:
if user == str(i['user']):
print('用户已存在!')
break
else:
print('用户不存在!')
# 缺陷输入1111会打印3遍用户不存在
for i in users:
if user == str(i['user']):
print('用户已存在!')
break
else:
print('用户不存在!')
******内置函数range()******
range(n) 默认生成0 ~ n-1的整数序列。对于这个序列我们可以通过list()转化为列表类型的数据。
range(n, m)左闭右开默认生成从n ~ m-1的整数序列。 对于这个序列我们可以通过list()转化为列表类型的数据。
range(n, m , k)左闭右开n初始值m-1结束值 k步长 递增或者递减的整数序列。
默认生成从n ~ m-1并且间隔k的整数序列。 对于这个序列我们可以通过list()转化为列表类型的数据。
# 示例:
print(list(range(10))) # 输出结果: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(range(1, 10))) # 输出结果: [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(range(2, 8, 2))) # 输出结果: [2, 4, 6]
print(list(range(101, 5, -5)))
# 输出结果: [101, 96, 91, 86, 81, 76, 71, 66, 61, 56, 51, 46, 41, 36, 31, 26, 21, 16, 11, 6]
print(list(range(5, 101, 5)))
# 输出结果: [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
******元组拆包*****
示例:
tu = (111, 222)
a, b = tu
print(a, b) # 输出结果111 222
******函数*****
1. 常用的内置函数
type():查看数据的类型
id() 查看数据的内存地址
len():查看数据的长度
range() 生成数据
2. 函数的定义
def 函数名():
# 函数内部的功能代码
# 函数内部的功能代码
# 函数内部的功能代码
可以将单一的功能封装成一个函数,在需要使用该功能的时候直接调用函数就可以了。
函数的作用: 封装代码。
函数的意义:提高代码的重用率。
函数的命名规范可以由数字下划线组成不能使用数字开头不能使用python关键字不要和内置函数和模块第三方模块官方库重名。
函数的命名风格:推荐使用下划线命名法。
示例:
def func(n):
for i in range(n):
for j in range(i + 1):
print('* ', end='')
print()
func(5)
3. 函数的参数:定义在函数后面的括号中
定义的参数叫形参,调用函数的时候传入的参数叫实参。
示例:
def add_number(a, b):
print('a+b: ', a + b)
add_number(3, 5)
4. 函数的返回值return
# 注意如果接收到的数据为None 说明没有返回值
示例:
def add_number(a, b):
return a + b
res = add_number(3, 5)
print(res)

View File

@ -0,0 +1,145 @@
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******函数的返回值*****
函数中的返回值是由return来决定的。
函数中没有return就没有返回值调用函数得到的结果就是None。
函数中返回多个值直接下载return后面用逗号隔开就可以。
当函数执行到return之后就会直接跳出函数返回结果后面的代码都不会再执行了。
******函数的参数*****
1. 实参分类(实参可以是变量):
位置传参/位置参数:通过位置按顺序传递
关键字传参/关键字参数:通过参数名指定参数进行传递
示例:
def add_number(a, b):
print('a+b: ', a + b)
return a + b
# 位置传参
res = add_number(3, 5)
# 关键字传参
res1 = add_number(b=9, a=10)
print(res, res1)
注意点:
位置参数与关键字参数可以一起用。
但是同时使用时,位置参数写前面,关键字参数写后面。
示例:
def add_number(a, b, c):
return a + b + c
# 位置传参 + 关键字传参
res = add_number(3, c=5, b=4)
print(res)
2. 形参:函数括号里面的就是形参
形参的分类:
必备参数(必须参数):定义了几个参数就要传递几个参数。
默认参数(缺省参数):可传可不传,不传的情况下使用默认值,传了的情况下使用传的值。
不定长参数:位置可前可后,但是一般放在后面。
*args接收0个或多个位置参数
**kwargs接收0个或多个关键字参数
示例:
# 必备参数
def add_number(a, b, c):
return a + b + c
res = add_number(3, 7, 8)
print(res)
# 默认参数: 可传可不传
def add_number1(a, b, c=90):
return a + b + c
res1 = add_number1(3, 7, 8)
res2 = add_number1(3, 87)
print(res1, res2)
# 不定长参数
def add_number2(a, b, c, *args):
print('a=', a)
print('b=', b)
print('c=', c)
print(args)
add_number2(3, 7, 8, 45, 55, 6, 66)
def add_number2(a, b, c, **kwargs):
print('a=', a)
print('b=', b)
print('c=', c)
print(kwargs)
add_number2(a=3, b=7, c=8, d=45, e=55, f=6, g=66)
******函数参数的拆包*****
函数定义:
*:表示接收位置参数的不定长参数
**:表示接收关键字参数的不定长参数
示例:
def func(*args, **kwargs):
print(args)
print(kwargs)
func(11,22,33, c = 7, d = 9, e = 10)
# 输出结果:(11, 22, 33)
# {'c': 7, 'd': 9, 'e': 10}
函数调用:
*:可以对元组或列表拆包
**:可以对字典拆包
示例:
def func(a, b, c, d):
print(a)
print(b)
print(c)
print(d)
tu= (11, 22, 33, 44)
li = [333, 555, 777, 888]
dic = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# 对元组,列表进行拆包
func(*tu)
func(*li)
# 对字典进行拆包
func(**dic)
******函数的作用域*****
1. 全局变量&局部变量
全局变量:直接定义在文件/模块中的变量。在该文件的任何地方都可以访问。
局部变量:定义在函数内部的变量。只有在函数内部才可以访问。
示例:
# 全局变量
a = 100
def func():
# 局部变量
b = 10
print('打印全局变量a=', a)
print('打印局部变量b=', b)
print('打印全局变量a=', a)
2. 作用域
局部变量的作用域:函数内部
函数参数的作用域:函数内部
3. 在函数内部定义全局变量使用global进行声明
示例:
def func(a, b):
# 全局变量
global c
c = 10
print('a=', a)
print('b=', b)
print('c=', c)
func(1, 3)
print(c)
4. 函数内部变量和全局变量同名时,在函数内部访问该变量,会优先使用局部变量
示例:
a = 100
def func():
a = 10
print('a=', a)
func() # 输出结果: a= 10

View File

@ -0,0 +1,221 @@
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******内置函数*****
1. min()获取最小值;只能对一组数据进行操作,不能对字符串进行操作。
示例:
tu = (11, 22, 33)
print('获取元组中的最小值:', min(tu))
li = [345, 789, 890]
print('获取列表中的最小值:', min(li))
dic = {'a': 1, 'b': 9}
print(min(dic.values()))
2. max()获取最大值;只能对一组数据进行操作,不能对字符串进行操作。
示例:
tu = (11, 22, 33)
print('获取元组中的最大值:', max(tu))
li = [345, 789, 890]
print('获取列表中的最大值:', max(li))
dic = {'a': 1, 'b': 9}
print(max(dic.values()))
3. sum()求和;只能对一组数据进行操作,不能对字符串进行操作。
示例:
tu = (11, 22, 33)
print('获取元组中元素之和:', sum(tu))
li = [345, 789, 890]
print('获取列表中元素之和:', sum(li))
dic = {'a': 1, 'b': 9}
print(sum(dic.values()))
4. enumerate()获取数据的索引和值
示例:
dic = {'a': 1, 'b': 9}
li = [345, 789, 890]
tu = (11, 22, 33)
print(list(enumerate(tu)))
# 输出结果:[(0, 11), (1, 22), (2, 33)]
print(list(enumerate(li)))
# 输出结果:[(0, 345), (1, 789), (2, 890)]
print(list(enumerate(dic)))
# 输出结果:[(0, 'a'), (1, 'b')]
5. filter(参数1 参数2)
参数1函数过滤的规则
参数2需要过滤的数据
filter会根据参数-函数的返回值是True还是False来决定数据要不要过滤
示例:
li = [11, 22, 34, 6, 345, 789, 890]
def fun(x):
return x > 50
res = filter(fun, li)
print(list(res))
6. 匿名函数lambda 函数参数: 返回值
应用场景:一般用于非常简单的函数(函数内部只有一行代码)
比如结合过滤器filter()使用(当成别的函数的参数)
示例:
li = [11, 22, 34, 6, 345, 789, 890]
res = filter(lambda x: x>50, li)
print(list(res))
li1 = [11, 22, 34, 6, 345, 789, 890]
li2 = [11, 22, 33, 44, 565, 890, 789, 5, 6, 7, 8]
print(list(filter(lambda x: x in li1, li2)))
print(list(filter(lambda x: x % 5 == 0, range(101))))
7. eval()能够识别字符串中的有效python表达式
示例:
str1 = "{'a': 1, 'b': 2, 'c': 3}"
print(type(str1))
# 输出结果:<class 'str'>
print(type(eval(str1)))
# 输出结果:<class 'dict'>
str2 = "[11, 22, 33, 44]"
print(type(eval(str2)))
# 输出结果:<class 'list'>
# 如果eval需要识别的字符串里面是个变量名会打印出变量对应的值
b = 111
str3 = 'b'
print(eval(str3))
# 输出结果111
# 注意点:只能去掉一层引号
str4 = "'bcd'"
print(eval(str4))
# 输出结果bcd
8. zip()聚合打包
注意zip对象只能进行一次强制转换
示例:
li1 = ['name', 'age', 'gender']
li2 = ['flora', 18, 'female']
res = zip(li1, li2)
print(dict(res))
# 输出结果:{'name': 'flora', 'age': 18, 'gender': 'female'}
res1 = zip(li1, li2)
print(list(res1))
# 输出结果:[('name', 'flora'), ('age', 18), ('gender', 'female')]
# 按照顺序一一对应,长度不一致的情况下,只取最短的
li3 = ['name', 'age', 'gender', 'info']
li4 = ['flora', 18, 'female']
res2 = zip(li3, li4)
print(dict(res2))
# 输出结果:{'name': 'flora', 'age': 18, 'gender': 'female'}
res3 = zip(li3, li4)
print(list(res3))
# 输出结果:[('name', 'flora'), ('age', 18), ('gender', 'female')]
# zip扩展使用
示例:
li1 = [11, 22, 33, 44]
li2 = [1, 2, 3, 4, 5]
li3 = [111, 222, 333, 444, 555]
li4 = [11, 12, 13, 14, 15]
res1 = zip(li1, li2, li3, li4)
print(tuple(res1)) # 输出结果:[(11, 1, 111, 11), (22, 2, 222, 12), (33, 3, 333, 13), (44, 4, 444, 14)]
res2 = zip(li1, li2, li3, li4)
print(list(res2)) # 输出结果:((11, 1, 111, 11), (22, 2, 222, 12), (33, 3, 333, 13), (44, 4, 444, 14))
res3 = zip(li1, li2, li3, li4)
print(dict(res3)) # 报错ValueError: dictionary update sequence element #0 has length 4; 2 is required
******文件的操作*****
1. 打开文件
open(参数1 参数2, encoding='utf8')
参数1文件名/文件路径
参数2文件打开的模式
文件打开的模式:
r读取文件文件不存在会报错。
a追加写入 在文件后面写入新的内容,原有内容不变;文件不存在会新建一个。
w覆盖写入, 覆盖原有文件内容,写入新的内容;文件不存在会新建一个。
# 以下三种模式是以二进制的模式打开文件(常用于图片视频等文件的操作)
rb读取文件文件不存在会报错。
ab追加写入 在文件后面写入新的内容,原有内容不变;文件不存在会新建一个。
wb覆盖写入, 覆盖原有文件内容,写入新的内容;文件不存在会新建一个。
文件读写操作的模式(扩展):
r+:读取文件并写入内容;文件不存在会报错。
a+:读取文件并追加写入, 在文件后面写入新的内容,原有内容不变;文件不存在会新建一个。
w+:读取文件并覆盖写入, 覆盖原有文件内容,写入新的内容;文件不存在会新建一个。
# 以下三种模式是以二进制的模式打开文件并写入内容(常用于图片视频等文件的操作)
rb+:读取文件并写入内容;文件不存在会报错。
ab+:读取文件并追加写入, 在文件后面写入新的内容,原有内容不变;文件不存在会新建一个。
wb+:读取文件并覆盖写入, 覆盖原有文件内容,写入新的内容;文件不存在会新建一个。
2. 读取文件
文件读取的方法:
read()读取文件中所有的内容
readline()读取一行内容
readlines()按行读取所有内容,返回一个列表
3. 关闭文件
关闭文件:
close()
4. 文件写入
文件写入的方法:
write()
# -------------- 基本读取操作 ---------------------
示例:
# 打开文件 encoding='utf8'是可选参数
# f = open(file='flora_0213_notes.txt', mode='r', encoding='utf8')
f = open('flora_0213_notes.txt', 'r', encoding='utf8')
# 读取文件
content = f.read()
# 打印文件内容
print(content)
# 关闭文件
f.close()
# -------------- 指定路径读取 ----------------------
示例:
f = open(r'E:\PycharmProject\ChyClass\UITest\Test.py', 'r', encoding='utf8')
print(f.readlines())
f.close()
# -------------- 写入文件 ----------------------
示例:
f = open('test4.txt', 'w', encoding='utf8')
f.write('4444' + '\n')
f.close()
# -------------- 读取写入图片----------------------
示例:
# 读取图片
f = open('picture.jpg', 'rb')
content = f.read()
print(content)
# 写入图片
f2=open('picture.jpg', 'wb')
f2.write(content)
f.close()
f2.close()
5. 文件上下文管理器对象
with 语句
语法格式:
with open(文件名,打开模式) as 接收文件句柄的变量:
# 文件的读写操作
使用with操作文件的优点不用自己关闭文件文件会自动关闭。
示例:
with open('test.txt', 'r', encoding='utf8') as f:
print(f.read())

View File

@ -0,0 +1,165 @@
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******模块的导入*****
模块就是python文件一个py文件称之为一个模块。
import 模块名 (同级目录)
from 包名(文件夹) import 模块名
# 多层级下的模块导入-从项目路径下一级级的导入
from 包名.包名.包名(... import 模块名
示例:
目录结构如下:
python27Class/LearningNotesTXT/test1.py
python27Class/test.py
python27Class/FloraHomeWork_0225.py
在FloraHomeWork_0225.py中要用到test.py以及test1.py中的变量和函数
# 第一种导入方式:
import test
# 第二种导入方式:
from python27Class import test
from python27Class.LearningNotesTXT import test1
******标识符*****
python中自己起的名字都叫标识符变量名函数名模块名包名类名
标识符:只能由数字字母下划线组成,不能使用数字开头。
******python中的包*****
新建python的包包下面会默认带有__init__.py文件
from 包名 import __init__.py中的变量
示例:
目录结构如下:
python27Class/Pack/__init__.py/变量aaa
python27Class/FloraHomeWork_0225.py
在FloraHomeWork_0225.py中导入
from python27Class.Pack import aaa
print(aaa)
******导入模块中的某个变量(函数、类)*****
from 模块名 import 变量名
from 包名(文件夹).模块 import 变量名/函数名(多个用逗号隔开)
示例:
目录结构如下:
python27Class/Pack/test3.py
python27Class/FloraHomeWork_0225.py
在FloraHomeWork_0225.py中导入
# 导入变量
from python27Class.Pack.test3 import test3
# 导入函数
from python27Class.Pack.test3 import func_03
# 调用变量以及函数
print(test3)
func_03()
******导入的时候起别名*****
from 模块名 import 变量名 as 别名(自定义的名称)
示例:
from random import randint as rt
print(rt(1, 100))
******python内置的魔法变量__name__******
注意:在进行模块导入的时候,会将被导入的模块执行一遍
__name__的值不是固定的
直接运行该文件__name__值是__main__
在进行模块导入的时候, __name__的值是导入的模块名/包名(文件夹).模块名
示例:
python27Class/Pack/test3.py/print('test3.py中的__name__', __name__)
python27Class/FloraHomeWork_0225.py
在FloraHomeWork_0225.py中导入
from python27Class.Pack import test3 # 打印test3.py中的__name__ python27Class.Pack.test3
如果不希望当前模块中的某些代码在被导入的时候被执行,可以用如下方式解决:
# 这个条件只有在直接运行的时候才会成立。
# 通过模块导入的方式,该条件不会成立。
if __name__ == '__main__':
print('被其他模块导入的时候,这部分代码不会执行')
******查看模块导入的搜索路径******
import sys
for i in sys.path:
print(i)
******路径处理******
# 相对路径表示法:
. 表示当前目录
.. 表示父级目录
示例:
import os
# 获取绝对路径 .表示当前文件
res = os.path.abspath('.')
print(res)
# 获取当前文件的父级目录的绝对路径
print(os.path.abspath('..'))
# 获取当前文件的父级目录的绝对路径
res = os.path.abspath(__file__)
print(os.path.dirname(res))
# 获取项目路径,通过是通过这样的方法
Basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
******路径拼接******
os.path.join()
示例:
import os
Basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(os.path.join(Basedir, 'ChyClass'))
******魔法变量__file__******
__file__表示当前文件的文件名
注意pycharm下面做了优化处理打印的是一个文件路径
示例:
# 打印的结果是一样的,但是出来路径是斜杠/
print(__file__) # 输出结果E:/PycharmProject/ChyClass/python27Class/FloraHomeWork_0225.py
# 打印的结果是一样的,但是打印出来路径是反斜杠\
print(os.path.abspath(__file__)) # 输出结果E:\PycharmProject\ChyClass\python27Class\FloraHomeWork_0225.py
******OS模块中的扩展方法******
Linux命令 os模块中的方法
pwd os.getcwd() 获取当前的工作路径
cd os.chdir() 切换路径
ls os.listdir() 获取当前工作路径下的文件和文件夹信息
mkdir os.mkdir() 当前工作路径下创建文件夹
rmdir os.rmdir() 当前工作路径下删除文件夹
os.path.isfile 判断给定的路径是否文件路径
os.path.isdir 判断给定的路径是否是文件夹路径
示例:
import os
# 获取当前的工作路径
print(os.getcwd())
# 切换路径到C盘
os.chdir('C:')
print(os.getcwd())
# 获取当前工作路径下的文件和文件夹信息
print(os.listdir('..'))
# 当前工作路径下创建文件夹
os.mkdir('ccca') # 如果已存在,无法创建,会报错
# 判断给定的路径是否文件路径
print(os.path.isfile('E:\PycharmProject\ChyClass\python27Class'))
# 判断给定的路径是否是文件夹路径
print(os.path.isdir('E:\PycharmProject\ChyClass\python27Class'))

View File

@ -0,0 +1,126 @@
=================================
HomeWork
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******异常******
1. 对于有可能会出错的代码, 我们可以对这行代码进行异常捕获。
try-except
try-except-else
try-except-else-finally
try-except-finally
示例:
try:
a = int(input('请输入一个数字:'))
except:
print('出错啦try里面的代码出现了异常执行except中的代码')
else:
print('try里面的代码没有出现异常的时候执行else中的代码')
finally:
print('不管代码是否出现异常,都会执行!')
2. 捕获指定类型的异常
示例:
try:
a = int(input('请输入一个数字:'))
print(b)
except NameError: # 指定异常才会被捕获。出现其他异常还是会报错。
print('出错啦出现NameError会打印')
3. 可以定义变量来接收异常
示例:
try:
a = int(input('请输入一个数字:'))
print(b)
except NameError as e:
print('当前出错的原因:', e) # 输出结果name 'b' is not defined
print('出错啦出现NameError会打印')
4. 捕获多个异常
示例:
# 方法一使用多个except不同的异常类型可以做不同的处理
try:
a = int(input('请输入一个数字:'))
print(b)
except NameError as e:
print('当前出错的原因:', e)
print('出错啦出现NameError会打印')
except ValueError as e2:
print('当前出错的原因:', e2)
print('出错啦出现ValueError会打印')
# 方式二一个except不同异常做相同处理
try:
a = int(input('请输入一个数字:'))
print(b)
except (NameError, ValueError) as e:
print('当前出错的原因:', e)
print('出错啦出现NameError, ValueError会打印')
# 注意上述代码中try的第一行代码出现异常try中的第二行代码就不会执行了
5. 捕获不确定的异常, 可以直接捕获常见异常类型的父类
示例:
try:
import requests
requests.ger(url='www.baidu.com')
except Exception as e:
print('出错的原因:', e)
6. else场景应用
示例:
import os
# 复制指定路径下的文件到当前文件所在的目录
def file_copy(path):
try:
file_list = os.listdir(path)
except FileNotFoundError as e:
print('你传入的路径不对,出现了错误,错误提示{}'.format(e))
# 获取文件路径没有出错才执行以下代码
else:
for file in file_list:
# 定位目标目录的文件
file_path = os.path.join(path, file)
# 如果是文件,则进行文件复制
if os.path.isfile(file_path):
# 读取文件的内容
with open(file_path, 'rb') as f:
content = f.read()
# 将上面读取到的内容写入到新文件中, 新文件跟当前文件同级并且命名带有cp
# with open(os.path.join(os.getcwd(), 'cp' + file), 'wb') as f:
with open('cp' + file, 'wb') as f:
f.write(content)
file_copy('path')
7. finally应用场景
示例:
# 通过finally来关闭文件
f = open('case.txt', 'w', encoding='utf-8')
try:
n= input('请输入数字:')
except:
f.write('代码错误了!')
else:
f.write('代码没有错误了!')
finally:
print('finally执行了')
f.close()
8. raise主动抛出异常
示例:
print('-----------------------')
# raise ValueError('这个自定的错误提示')
raise AssertionError
print('-----------------------')
9. assert断言
excepted = '用例执行通过'
result = '用例执行未通过'
assert excepted == result # 不相等会抛出异常AssertionError

View File

@ -0,0 +1,243 @@
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******面向对象******
******类class******
1. 类的定义
关键字class
语法:
class 类名:
# 类里面的代码
类名命名规范遵循标识符的命名规范风格采用大驼峰命名法例如CatType
示例:
class Cat:
pass
class Dog:
pass
class TestCase:
pass
2. 通过类创建对象
对象 = 类名()
关于对象,有人叫对象,也有人叫实例。
通过类来创建对象(实例化对象)。可以创建多个对象,每个对象的内存地址都不一样。
示例:
class Cat:
pass
# 通过类来创建对象(实例化对象)。可以创建多个对象,每个对象的内存地址都不一样。
kitty = Cat()
print(id(kitty)) # 输出结果2108715911296
coffee = Cat()
print(id(coffee)) # 输出结果2108716016880
******类属性和实例属性******
1. 类属性
这一类事物拥有的共同特征,我们通常会定义为类属性。
在类里面直接定义的变量,叫做类属性。
类属性:可以通过类和对象去访问
有两种方式可以访问类属性:
通过对象访问类属性:对象名.属性名。
通过类访问属性:类名.属性名。
示例:
class Cat:
# 类属性
leg = '四条腿'
tail = '长尾巴'
# 通过对象访问类属性:对象名.属性名
kitty = Cat()
print(kitty.leg) # 输出结果:四条腿
coffee = Cat()
print(coffee.tail) # 输出结果:长尾巴
# 通过类访问属性:类名.属性名
print(Cat.leg) # 输出结果:四条腿
2. 实例属性
每个对象的属性值都有可能不一样,就应该定义为实例属性(对象属性)。
实例属性的定义:对象.属性名=属性值。
对象属性(实例属性):只能对象自己能用。
示例:
class Cat:
# 类属性
leg = '四条腿'
tail = '长尾巴'
# 实例化对象
kitty = Cat()
coffee = Cat()
# 给对象添加属性
kitty.name = 'kitty'
kitty.age = 2
coffee.name = 'coffee'
coffee.age = 3
# 通过对象访问对象属性:对象名.属性名
print(kitty.name) # 输出结果kitty
print(kitty.age) # 输出结果2
print(coffee.name) # 输出结果kitty
print(coffee.age) # 输出结果3
3. 关于如何在类里面定义对象属性
定义在类里面的函数叫方法。
__init__方法
初始化方法;
在创建对象的时候,会自动调用执行里面的代码。
关于方法中的第一个参数selfself代表对象不用手动传参调用该方法时会自动传入。
示例:
class Cat:
# 类属性
leg = '四条腿'
tail = '长尾巴'
def __init__(self):
# 初始化方法
print('这里是打印self', id(self), self)
print('这个是__init__方法在调用')
kitty = Cat() # 输出结果这里是打印self 1396410304640 <__main__.Cat object at 0x00000145208A4880>
print('这里是打印kitty', id(kitty), kitty)
# 输出结果这里是打印self 1396410304640 <__main__.Cat object at 0x00000145208A4880>
print('----------------------')
coffee = Cat() # 输出结果这里是打印self 2197480466656 <__main__.Cat object at 0x000001FFA40AE8E0>
print('这里是打印coffee', id(coffee), coffee)
# 输出结果这里是打印coffee 1796880263392 <__main__.Cat object at 0x000001A25E68E8E0>
__init__方法的作用初始化对象属性
示例:
class Cat:
# 类属性
leg = '四条腿'
tail = '长尾巴'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
kitty = Cat('hello kitty', 1, 'female')
print(kitty.name)
coffee = Cat('coffee cat', 2, 'male')
print(kitty.age)
4. 类里面的方法
特征 + 行为
特征:属性(类属性和实例属性)
行为:方法(类方法和实例方法)
方法的本质就是类里面的函数。
实例方法:
第一个参数时self, self代表的是对象本身哪个对象调用该方法self就代表哪个对象。
实例方法只能通过对象去调用。
实例方法不能通过类去调用,调用会报错。
类方法:
@classmethod进行装饰标识
第一个参数时cls cls代表的是类本身。
可以通过类和对象去调用。
静态方法:
@staticmethod进行装饰
可以通过类和对象去调用。
示例:
class Cat:
# 类属性
leg = '四条腿'
tail = '长尾巴'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
# 实例方法
def skill_01(self, skill_name):
print('{}会{}'.format(self.name, skill_name))
# 实例方法
def skill_02(self):
print('{}会爬树!'.format(self.name))
@classmethod
def class_method(cls):
print('这是一个类方法!')
print('打印cls', cls)
@staticmethod
def static_method():
print('这是一个静态方法!')
# 通过对象调用实例方法
kitty = Cat('hello kitty', 1, 'female')
kitty.skill_01('跳舞')
coffee = Cat('coffee cat', 2, 'male')
coffee.skill_02()
# 通过类迪调用实例方法
# Cat.skill_02() # 报错TypeError: skill_02() missing 1 required positional argument: 'self'
print('-------------------------')
# 通过类访问类方法:类名.类方法名
Cat.class_method()
# 通过对象调用类方法:对象名.类方法名
kitty.class_method()
print('-------------------------')
# 通过类访问静态方法:类名.类方法名
Cat.static_method()
# 通过对象调用静态方法:对象名.类方法名
kitty.static_method()
5. 关于类方法,静态方法,实例方法的应用场景
类方法:在方法内部只会使用到类属性。
静态方法:方法内部既不会使用类相关的属性和方法, 也不会使用实例(对象)相关的属性和方法。
实例方法:在方法内部会使用到对象相关的属性或方法,那么适合定义为对象方法。
示例:
class Cat:
# 类属性
leg = '四条腿'
tail = '长尾巴'
def __init__(self, name, age, gender):
# 实例(对象)属性
self.name = name
self.age = age
self.gender = gender
# 实例方法
def skill_01(self):
print('{}会跳舞!'.format(self.name))
self.move()
def move(self):
print('快速移动')
# 类方法
@classmethod
def class_method(cls):
print('这是猫类的共同特征:{}{}'.format(cls.leg, cls.tail))
print('打印cls', cls)
#静态方法
@staticmethod
def static_method():
print('里面的代码和类和对象没有太多相关性!')
kitty = Cat('kitty', 1, 'female')
kitty.skill_01()

View File

@ -0,0 +1,367 @@
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******类属性的分类******
类属性的分类:
1. 公有属性:既可以在类内部使用,又可以在类的外部被调用。
2. 私有属性:使用双下划线开头。只能在类外部使用,在类外面无法被调用。
示例:
class Cat:
# 公有属性
attr = 'I have tail'
# 私有属性
__attr = 'I have 4 legs'
def print_attr(self):
print('在类的内部访问公有属性', self.attr)
print('在类的内部访问公有属性', self.__attr)
Kitty = Cat()
print('在类的外部访问公有属性', Kitty.attr)
# 在类外部调用私有属性会报错: AttributeError: 'Cat' object has no attribute '__attr'
# print('在类的外部访问公有属性', Kitty.__attr)
Kitty.print_attr()
******类定义的两种方式******
# 这两种定义类的方式无差别
# 类定义的第一种方式不写继承的父类默认继承object。
class MyTest:
pass
# 类定义的第二种方式在类名的括号后面指定继承object这个类。
class MyClass(object):
pass
# object: python中所有类的基类祖宗类
******类的继承******
子类通过继承父类,能够获取父类中定义的所有属性和方法(私有属性除外)。
注意:父类不能使用子类的属性和方法。
继承的作用:简化代码,提高代码的重用性。
示例:
未用到继承之前的代码:
class PhoneV1(object):
def call(self):
print('打电话的功能')
class PhoneV2(object):
def call(self):
print('打电话的功能')
def listen_music(self):
print('听音乐的功能')
def send_message(self):
print('发短信的功能')
class PhoneV3(object):
def call(self):
print('打电话的功能')
def listen_music(self):
print('听音乐的功能')
def send_message(self):
print('发短信的功能')
def we_chat(self):
print('聊微信的功能')
def plag_game(self):
print('玩游戏的功能')
用到继承之后的代码:
class PhoneV1(object):
def call(self):
print('打电话的功能')
class PhoneV2(PhoneV1):
def listen_music(self):
print('听音乐的功能')
def send_message(self):
print('发短信的功能')
class PhoneV3(PhoneV2):
def we_chat(self):
print('聊微信的功能')
def play_game(self):
print('玩游戏的功能')
# v1对应的类
print('------v1对应的类------')
v1 = PhoneV1()
v1.call()
# 父类不能调用子类的方法
# v1.listen_music() # 报错AttributeError: 'PhoneV1' object has no attribute 'listen_music'
# v2对应的类
print('------v2对应的类------')
v2 = PhoneV2()
# 子类可以调用父类的方法
v2.call()
v2.listen_music()
v2.send_message()
# v3对应的类
print('------v3对应的类------')
v3 = PhoneV3()
v3.call()
v3.listen_music()
v3.send_message()
v3.we_chat()
v3.play_game()
******重写父类方法******
在子类中定义跟父类同名的方法就是重写父类方法。
class PhoneV1(object):
def call(self):
print('打电话的功能')
class PhoneV2(PhoneV1):
def listen_music(self):
print('听音乐的功能')
def send_message(self):
print('发短信的功能')
# 重写父类的方法
def call(self):
print('打视频电话的功能')
class PhoneV3(PhoneV2):
def we_chat(self):
print('聊微信的功能')
def play_game(self):
print('玩游戏的功能')
print('------v1对应的类------')
v1 = PhoneV1()
v1.call() # 输出结果:打电话的功能
print('------v2对应的类------')
v2 = PhoneV2()
# 子类可以调用父类的方法
v2.call() # 输出结果:打视频电话的功能
print('------v3对应的类------')
v3 = PhoneV3()
v3.call() # 输出结果:打视频电话的功能
******调用被重写的父类方法******
方式一:父类名.方法名(self)
方式二super().方法名
示例:
class PhoneV1(object):
def call(self):
print('打电话的功能')
class PhoneV2(PhoneV1):
def we_chat(self):
print('聊微信的功能')
def play_game(self):
print('玩游戏的功能')
# 重写父类的方法
def call(self):
print('打视频电话的功能')
print('**********接下来想打语音电话')
# 调用父类里面的call()
# 方式一:父类名.方法名(self)
PhoneV1.call(self)
# 方式二super().方法名
super().call()
v2 = PhoneV2()
v2.call()
******super()的应用场景******
主要是代码的扩展,扩展新功能。
示例:
class MyClass:
def __init__(self, a, b):
self.a = a
self.b = b
def number(self):
print('a+b=', self.a + self.b)
class MyClassV2(MyClass):
def number(self):
# 调用父类原有的方法
super().number()
# 在原有方法的基础上扩展新功能
print('a+b=', self.a / self.b)
m = MyClassV2(11, 22)
m.number()
******动态获取属性******
getattr获取类属性:
参数1
参数2属性名
参数3默认值。如果属性不存在则返回该值
示例:
# 示例1
class TestData:
url = 'http://www.baidu.com'
method = 'get'
# getattr获取类属性
res = getattr(TestData, 'url')
print(res) # 输出结果http://www.baidu.com
res1 = getattr(TestData, 'result', 'python')
print(res1) # 输出结果python
# 示例2
class TestData:
url = 'http://www.baidu.com'
method = 'get'
name = input('请输入你要获取的属性名:')
# getattr获取类属性
res = getattr(TestData, name, 'None')
print(res) # 输出结果http://www.baidu.com
******动态设置属性******
setattr设置属性值
参数1
参数2属性名
参数3属性值
示例1
# 类外面定义类属性
# 方式一:类.属性名=属性值
TestData.result = 'Pass'
print(TestData.result)
# 方式二动态setattr设置属性
setattr(TestData, 'para', 'username')
print(TestData.para) # 输出结果username
示例2
class TestData:
url = 'http://www.baidu.com'
method = 'get'
# 将下面2个列表title作为属性名data作为属性值一一对应起来
title = ['name', 'age', 'gender']
data = ['flora', 26, 'female']
# 以下方法是不可取的会报错AttributeError: type object 'TestData' has no attribute 'title'
# TestData.title[0] = data[0]
# print(TestData.title[0])
# setattr(TestData, title[0], data[0])
# setattr(TestData, title[1], data[1])
# setattr(TestData, title[2], data[2])
for i in range(len(title)):
setattr(TestData, title[i], data[i])
print(TestData.name, TestData.age, TestData.gender)
# 输出结果flora 26 female
******动态删除属性******
delattr动态删除属性
参数1
参数2属性名
示例:
class TestData:
url = 'http://www.baidu.com'
method = 'get'
# 方式一关键字del
del TestData.url
print(TestData.url) # 报错AttributeError: type object 'TestData' has no attribute 'url'
# 方式二delattr
name = input('请输入你要删除的属性:')
delattr(TestData, name)
******判断属性是否存在******
hasattr判断属性是否存在
参数1类名
参数2属性名
如果属性存在返回True如果属性不存在返回False
示例:
class TestData:
url = 'http://www.baidu.com'
method = 'get'
del TestData.url
res = hasattr(TestData, 'url')
print(res) # 输出结果False
res1 = hasattr(TestData, 'method')
print(res1) # 输出结果True
******多继承******
子类可以继承多个父类,子类都可以用到继承的父类中的属性和方法。
示例:
class BaseA(object):
attr_a = 100
def func_a(self):
print('func_a----------aaa')
class BaseB(object):
attr_b = 900
def func_b(self):
print('func_b----------bbb')
class MyTest(BaseA, BaseB):
pass
m = MyTest()
print(m.attr_a)
print(m.attr_b)
m.func_a()
m.func_b()
注意:
如果子类继承的父类里面都有相同的方法,在调用的时候,会先找第一个父类的方法,找到了就不会继续找了,没找到就会继续找下一个父类的方法。
如果子类自己也有跟父类相同的方法,在调用的时候,子类会优先使用自己的方法,不会去找父类的方法了。
示例:
class BaseA(object):
attr_a = 100
def func_a(self):
print('func_a----------aaa')
def func(self):
print('func_ab----------ab')
class BaseB(object):
attr_b = 900
def func_b(self):
print('func_b----------bbb')
def func(self):
print('func_bb----------bb')
class MyTest(BaseA, BaseB):
pass
# def func(self):
# print('func_cb----------cb')
m = MyTest()
m.func()

View File

@ -0,0 +1,4 @@
本次课程的内容:
1. 初步学习unittest
2. 学习如何编写测试用例
3. 学习如何通过测试套件运行测试并生成HTML测试报告

View File

@ -0,0 +1,21 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/5 20:42
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
def login_check(username=None, passwd=None):
"""
登录校验的函数
:param username:
:param passwd:
:return: dict type
"""
if username != None and passwd != None:
if username == 'flora' and passwd == '1234567Az':
return {'code': 0, 'mag': '登录成功'}
else:
return {'code': 1, 'mag': '账号或者密码不正确'}
else:
return {'code': 1, 'mag': '账号和密码不能为空'}

View File

@ -0,0 +1,82 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/5 21:11
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
"""
第一步创建测试套件
"""
suite = unittest.TestSuite()
"""
第二步加载测试用例到测试套件
"""
# 第一种:通过测试用例类去加载
# from python27Class.testCase import LoginTestCase
# loader = unittest.TestLoader()
# suite.addTest(loader.loadTestsFromTestCase(LoginTestCase))
# 第二种:通过测试用例模块去加载
# 用例加载器对象
# from python27Class import testCase
# loader = unittest.TestLoader()
# suite.addTest(loader.loadTestsFromModule(testCase))
# 第三种:通过路径去加载所有的测试用例 (推荐这一种)
# 注意默认去找指定路径中test开头的模块中的测试用例
# loader = unittest.TestLoader()
# suite.addTest(loader.discover(r'E:\PycharmProject\PythonClassChy\python27Class'))
# 第四种:一条条去加载
from python27Class.class03052020.testCase import LoginTestCase
case1 = LoginTestCase('test_login_pass')
suite.addTest(case1)
"""
综合第一步和第二步创建套件并加载用例
"""
# suite = unittest.defaultTestLoader.discover(r'E:\PycharmProject\PythonClassChy\python27Class')
"""
第三步(1)执行测试套件中的用例, 控制台生成报告
"""
# 仅执行,未生成测试报告
# 创建测试运行程序
runner = unittest.TextTestRunner()
runner.run(suite)
# ----------------------------------------------
# 执行并生成测试报告
"""
第三步(2)使用BeautifulReport来执行测试套件中的用例并生成报告
# 2个参数报告描述用例名称报告文件名
report_dir用来指定报告的存放位置
需要注释这两行代码
# runner = unittest.TextTestRunner()
# runner.run(suite)
否则运行生成报告的代码会报错TypeError: 'NoneType' object is not callable
"""
# from BeautifulReport import BeautifulReport
# br = BeautifulReport(suite)
# br.report('flora Auto-Test Report', 'brReport.html', report_dir=r'E:\PycharmProject\PythonClassChy\python27Class\testReport')
# ----------------------------------------------
"""
第三步(3)使用HTMLTestRunner来生成测试报告
stream表示报告存放的位置以及写入的模式
title表示报告的标题
tester表示测试人员
description表示对测试报告的描述
"""
# from HTMLTestRunner import HTMLTestRunner
# runner = HTMLTestRunner(stream=open(r'E:\PycharmProject\PythonClassChy\python27Class\testReport\newReport.html', 'wb'),
# title='flora Auto-Test Report',
# tester='flora',
# description='第一个版本的测试')
# runner.run(suite)

View File

@ -0,0 +1,83 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/5 20:23
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
from python27Class.class03052020.login import login_check
"""
# 定义测试用例类必须继承unittest.TestCase
# 定义测试用例在测试用例类中每一个以test开头的方法就是一条用例
# unittest中测试用例执行的顺序是根据方法名按ASCII码进行排序的
# unittest中会自动根据用例方法执行的时候是否出现断言异常来评判用例执行是否通过
"""
class LoginTestCase(unittest.TestCase):
# 第一步:准备用例数据
# 第二步:获取实际结果(调用功能函数,传入参数,获取实际结果)
# 第三步:断言(比对预期结果和实际结果)
def test_login_pass(self):
# 参数准备
data = {'username': 'flora', 'passwd': '1234567Az'}
# 预期结果准备
expect_result = {'code': 0, 'mag': '登录成功'}
# 获取实际结果
actual_result = login_check(**data)
# 断言
# assert expect_result == actual_result
self.assertEqual(expect_result, actual_result)
def test_login_user_error(self):
# 参数准备
data = {'username': 'flora.chen', 'passwd': '1234567Az'}
# 预期结果准备
expect_result = {'code': 1, 'mag': '账号或者密码不正确'}
# 获取实际结果
actual_result = login_check(**data)
# 断言
# assert expect_result == actual_result
self.assertEqual(expect_result, actual_result)
def test_login_pwd_error(self):
# 参数准备
data = {'username': 'flora', 'passwd': '1234567Aa'}
# 预期结果准备
expect_result = {'code': 1, 'mag': '账号或者密码不正确'}
# 获取实际结果
actual_result = login_check(**data)
# 断言
# assert expect_result == actual_result
self.assertEqual(expect_result, actual_result)
def test_login_user_is_null(self):
# 参数准备
data = {'passwd': '1234567Aa'}
# 预期结果准备
expect_result = {'code': 1, 'mag': '账号和密码不能为空'}
# 获取实际结果
actual_result = login_check(**data)
# 断言
# assert expect_result == actual_result
self.assertEqual(expect_result, actual_result)
def test_login_pwd_is_null(self):
# 参数准备
data = {'username': 'flora'}
# 预期结果准备
expect_result = {'code': 1, 'mag': '账号和密码不能为空'}
# 获取实际结果
actual_result = login_check(**data)
# 断言
# assert expect_result == actual_result
self.assertEqual(expect_result, actual_result)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,3 @@
本次课程的内容:
1. 学习unittest的数据驱动DDT
2. 学习如何读取excel中的数据以及往excel中写入数据

View File

@ -0,0 +1,3 @@
用例数据从用例中分离出来。
这种方式不用写多个测试用例。减少代码的冗余。
可以通过传一组数据的方式通过一个test case方法来执行。

View File

@ -0,0 +1,68 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/6 8:59
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
users = [{'user': 'python26', 'password': '123456'}]
def register(username, password1, password2):
"""
:param username:
:param password1:
:param password2:
:return:
"""
# 判断是否有参数为空
if not all([username, password1, password2]):
return {"code": 0, "msg": "所有参数不能为空"}
# 注册功能
for user in users: # 遍历出所有账号,判断账号是否存在
if username == user['user']:
# 账号存在
return {"code": 0, "msg": "该账户已存在"}
else:
if password1 != password2:
# 两次密码不一致
return {"code": 0, "msg": "两次密码不一致"}
else:
# 账号不存在 密码不重复,判断账号密码长度是否在 6-18位之间
if 6 <= len(username) >= 6 and 6 <= len(password1) <= 18:
# 注册账号
users.append({'user': username, 'password': password2})
return {"code": 1, "msg": "注册成功"}
else:
# 账号密码长度不对,注册失败
return {"code": 0, "msg": "账号和密码必须在6-18位之间"}
if __name__ == "__main__":
res = register('python14', '123456', '123456')
print(res)
"""
函数入参
注意参数传字符串类型不需要考虑其他类型
参数1账号
参数2密码1
参数2密码2
函数内部处理的逻辑
判断是否有参数为空
判断账号密码是否在6-18位之间
判断账号是否被注册过
判断两个密码是否一致
上面添加都校验通过才能注册成功其他情况都注册失败
各种情况的返回结果如下
注册成功 返回结果{"code": 1, "msg": "注册成功"}
有参数为空 返回结果 {"code": 0, "msg": "所有参数不能为空"}
两次密码不一致 返回结果{"code": 0, "msg": "两次密码不一致"}
账户已存在 返回结果{"code": 0, "msg": "该账户已存在"}
密码不在6-18位之间 返回结果{"code": 0, "msg": "账号和密码必须在6-18位之间"}
账号不在6-18位之间 返回结果{"code": 0, "msg": "账号和密码必须在6-18位之间"}
"""

View File

@ -0,0 +1,54 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/6 9:33
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import os
import unittest
from BeautifulReport import BeautifulReport
from python27Class.class03072020.demo1.testRegister import RegisterTestCase
"""
第一步创建测试套件
"""
suite = unittest.TestSuite()
"""
第二步1加载测试用例执行单条测试用例数据
case_data = {'expect_result': {"code": 0, "msg": "该账户已存在"}, 'data': ['python26', '123456', '123456']}
case = RegisterTestCase('test_register', case_data)
suite.addTest(case)
"""
"""
第二步2加载测试用例执行多条测试用例数据
"""
cases = [
{'expect_result': {"code": 0, "msg": "该账户已存在"}, 'data': ['python26', '123456', '123456']},
{'expect_result': {"code": 0, "msg": "两次密码不一致"}, 'data': ['python1', '12345655', '123456']},
]
for case_data in cases:
case = RegisterTestCase('test_register', case_data)
suite.addTest(case)
"""
第三步执行测试套件中的用例 使用BeautifulReport生成HTML测试报告
2个参数报告描述用例名称报告文件名
report_dir用来指定报告的存放位置
"""
# 要执行的测试用例的位置
path = os.path.dirname(os.path.abspath(__file__))
# 测试报告存放的路径
report_path = os.path.join(path, 'testReport')
b_report = BeautifulReport(suite)
b_report.report('Register Function Report by flora',
'register_beautiful_report.html',
report_dir=report_path
)

View File

@ -0,0 +1,27 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 9:47
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
from python27Class.class03072020.demo1.registerPage import register
class RegisterTestCase(unittest.TestCase):
def __init__(self, methodName, case_data):
super().__init__(methodName)
self.case_data = case_data
def test_register(self):
# 参数准备
data = self.case_data['data']
# 预期结果准备
expect_result = self.case_data['expect_result']
# 获取实际结果
actual_result = register(*data)
# 断言
# assert expect_result == actual_result
self.assertEqual(expect_result, actual_result)

View File

@ -0,0 +1,319 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 10:52
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
# -*- coding: utf-8 -*-
# This file is a part of DDT (https://github.com/datadriventests/ddt)
# Copyright 2012-2015 Carles Barrobés and DDT contributors
# For the exact contribution history, see the git revision log.
# DDT is licensed under the MIT License, included in
# https://github.com/datadriventests/ddt/blob/master/LICENSE.md
import inspect
import json
import os
import re
import codecs
from functools import wraps
try:
import yaml
except ImportError: # pragma: no cover
_have_yaml = False
else:
_have_yaml = True
__version__ = '1.2.2'
# These attributes will not conflict with any real python attribute
# They are added to the decorated test method and processed later
# by the `ddt` class decorator.
DATA_ATTR = '%values' # store the data the test must run with
FILE_ATTR = '%file_path' # store the path to JSON file
UNPACK_ATTR = '%unpack' # remember that we have to unpack values
index_len = 5 # default max length of case index
try:
trivial_types = (type(None), bool, int, float, basestring)
except NameError:
trivial_types = (type(None), bool, int, float, str)
def is_trivial(value):
if isinstance(value, trivial_types):
return True
elif isinstance(value, (list, tuple)):
return all(map(is_trivial, value))
return False
def unpack(func):
"""
Method decorator to add unpack feature.
"""
setattr(func, UNPACK_ATTR, True)
return func
def data(*values):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
"""
global index_len
index_len = len(str(len(values)))
return idata(values)
def idata(iterable):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
"""
def wrapper(func):
setattr(func, DATA_ATTR, iterable)
return func
return wrapper
def file_data(value):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
``value`` should be a path relative to the directory of the file
containing the decorated ``unittest.TestCase``. The file
should contain JSON encoded data, that can either be a list or a
dict.
In case of a list, each value in the list will correspond to one
test case, and the value will be concatenated to the test method
name.
In case of a dict, keys will be used as suffixes to the name of the
test case, and values will be fed as test data.
"""
def wrapper(func):
setattr(func, FILE_ATTR, value)
return func
return wrapper
def mk_test_name(name, value, index=0):
"""
Generate a new name for a test case.
It will take the original test name and append an ordinal index and a
string representation of the value, and convert the result into a valid
python identifier by replacing extraneous characters with ``_``.
We avoid doing str(value) if dealing with non-trivial values.
The problem is possible different names with different runs, e.g.
different order of dictionary keys (see PYTHONHASHSEED) or dealing
with mock objects.
Trivial scalar values are passed as is.
A "trivial" value is a plain scalar, or a tuple or list consisting
only of trivial values.
"""
# Add zeros before index to keep order
index = "{0:0{1}}".format(index + 1, index_len)
if not is_trivial(value):
return "{0}_{1}".format(name, index)
try:
value = str(value)
except UnicodeEncodeError:
# fallback for python2
value = value.encode('ascii', 'backslashreplace')
test_name = "{0}_{1}_{2}".format(name, index, value)
return re.sub(r'\W|^(?=\d)', '_', test_name)
def feed_data(func, new_name, test_data_docstring, *args, **kwargs):
"""
This internal method decorator feeds the test data item to the test.
"""
@wraps(func)
def wrapper(self):
return func(self, *args, **kwargs)
wrapper.__name__ = new_name
wrapper.__wrapped__ = func
# set docstring if exists
if test_data_docstring is not None:
wrapper.__doc__ = test_data_docstring
else:
# Try to call format on the docstring
if func.__doc__:
try:
wrapper.__doc__ = func.__doc__.format(*args, **kwargs)
except (IndexError, KeyError):
# Maybe the user has added some of the formating strings
# unintentionally in the docstring. Do not raise an exception
# as it could be that user is not aware of the
# formating feature.
pass
return wrapper
def add_test(cls, test_name, test_docstring, func, *args, **kwargs):
"""
Add a test case to this class.
The test will be based on an existing function but will give it a new
name.
"""
setattr(cls, test_name, feed_data(func, test_name, test_docstring,
*args, **kwargs))
def process_file_data(cls, name, func, file_attr):
"""
Process the parameter in the `file_data` decorator.
"""
cls_path = os.path.abspath(inspect.getsourcefile(cls))
data_file_path = os.path.join(os.path.dirname(cls_path), file_attr)
def create_error_func(message): # pylint: disable-msg=W0613
def func(*args):
raise ValueError(message % file_attr)
return func
# If file does not exist, provide an error function instead
if not os.path.exists(data_file_path):
test_name = mk_test_name(name, "error")
test_docstring = """Error!"""
add_test(cls, test_name, test_docstring,
create_error_func("%s does not exist"), None)
return
_is_yaml_file = data_file_path.endswith((".yml", ".yaml"))
# Don't have YAML but want to use YAML file.
if _is_yaml_file and not _have_yaml:
test_name = mk_test_name(name, "error")
test_docstring = """Error!"""
add_test(
cls,
test_name,
test_docstring,
create_error_func("%s is a YAML file, please install PyYAML"),
None
)
return
with codecs.open(data_file_path, 'r', 'utf-8') as f:
# Load the data from YAML or JSON
if _is_yaml_file:
data = yaml.safe_load(f)
else:
data = json.load(f)
_add_tests_from_data(cls, name, func, data)
def _add_tests_from_data(cls, name, func, data):
"""
Add tests from data loaded from the data file into the class
"""
for i, elem in enumerate(data):
if isinstance(data, dict):
key, value = elem, data[elem]
test_name = mk_test_name(name, key, i)
elif isinstance(data, list):
value = elem
test_name = mk_test_name(name, value, i)
if isinstance(value, dict):
add_test(cls, test_name, test_name, func, **value)
else:
add_test(cls, test_name, test_name, func, value)
def _is_primitive(obj):
"""Finds out if the obj is a "primitive". It is somewhat hacky but it works.
"""
return not hasattr(obj, '__dict__')
def _get_test_data_docstring(func, value):
"""Returns a docstring based on the following resolution strategy:
1. Passed value is not a "primitive" and has a docstring, then use it.
2. In all other cases return None, i.e the test name is used.
"""
if not _is_primitive(value) and value.__doc__:
return value.__doc__
else:
return None
def ddt(cls):
"""
Class decorator for subclasses of ``unittest.TestCase``.
Apply this decorator to the test case class, and then
decorate test methods with ``@data``.
For each method decorated with ``@data``, this will effectively create as
many methods as data items are passed as parameters to ``@data``.
The names of the test methods follow the pattern
``original_test_name_{ordinal}_{data}``. ``ordinal`` is the position of the
data argument, starting with 1.
For data we use a string representation of the data value converted into a
valid python identifier. If ``data.__name__`` exists, we use that instead.
For each method decorated with ``@file_data('test_data.json')``, the
decorator will try to load the test_data.json file located relative
to the python file containing the method that is decorated. It will,
for each ``test_name`` key create as many methods in the list of values
from the ``data`` key.
"""
for name, func in list(cls.__dict__.items()):
if hasattr(func, DATA_ATTR):
for i, v in enumerate(getattr(func, DATA_ATTR)):
test_name = mk_test_name(name, getattr(v, "__name__", v), i)
# 将用例描述信息改为用例数据的title字段
# 原代码test_data_docstring = _get_test_data_docstring(func, v)
test_data_docstring = v['title']
if hasattr(func, UNPACK_ATTR):
if isinstance(v, tuple) or isinstance(v, list):
add_test(
cls,
test_name,
test_data_docstring,
func,
*v
)
else:
# unpack dictionary
add_test(
cls,
test_name,
test_data_docstring,
func,
**v
)
else:
add_test(cls, test_name, test_data_docstring, func, v)
delattr(cls, name)
elif hasattr(func, FILE_ATTR):
file_attr = getattr(func, FILE_ATTR)
process_file_data(cls, name, func, file_attr)
delattr(cls, name)
return cls

View File

@ -0,0 +1,17 @@
先安装数据驱动
pip install ddt
DDT会自动遍历用例数据。
-----------------------------------------------------------
DDT执行用例后生成的报告会在方法名后加编号例如test_register_1。
-----------------------------------------------------------
但是如果需要显示每条用例执行时验证了什么功能需要修改DDT原码。
可以将DDT原码复制出来做如下修改
ddt.py中第284行代码test_data_docstring = _get_test_data_docstring(func, v)
用例数据中需要传入title:
cases = [
{'title': '该账户已存在', 'expect_result': {"code": 0, "msg": "该账户已存在"}, 'data': ['python26', '123456', '123456']},
{'title': '两次密码不一致', 'expect_result': {"code": 0, "msg": "两次密码不一致"}, 'data': ['python1', '12345655', '123456']},
]
然后倒入ddt的时候 需要导入我们新修改的ddt模块

View File

@ -0,0 +1,68 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/6 8:59
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
users = [{'user': 'python26', 'password': '123456'}]
def register(username, password1, password2):
"""
:param username:
:param password1:
:param password2:
:return:
"""
# 判断是否有参数为空
if not all([username, password1, password2]):
return {"code": 0, "msg": "所有参数不能为空"}
# 注册功能
for user in users: # 遍历出所有账号,判断账号是否存在
if username == user['user']:
# 账号存在
return {"code": 0, "msg": "该账户已存在"}
else:
if password1 != password2:
# 两次密码不一致
return {"code": 0, "msg": "两次密码不一致"}
else:
# 账号不存在 密码不重复,判断账号密码长度是否在 6-18位之间
if 6 <= len(username) >= 6 and 6 <= len(password1) <= 18:
# 注册账号
users.append({'user': username, 'password': password2})
return {"code": 1, "msg": "注册成功"}
else:
# 账号密码长度不对,注册失败
return {"code": 0, "msg": "账号和密码必须在6-18位之间"}
if __name__ == "__main__":
res = register('python14', '123456', '123456')
print(res)
"""
函数入参
注意参数传字符串类型不需要考虑其他类型
参数1账号
参数2密码1
参数2密码2
函数内部处理的逻辑
判断是否有参数为空
判断账号密码是否在6-18位之间
判断账号是否被注册过
判断两个密码是否一致
上面添加都校验通过才能注册成功其他情况都注册失败
各种情况的返回结果如下
注册成功 返回结果{"code": 1, "msg": "注册成功"}
有参数为空 返回结果 {"code": 0, "msg": "所有参数不能为空"}
两次密码不一致 返回结果{"code": 0, "msg": "两次密码不一致"}
账户已存在 返回结果{"code": 0, "msg": "该账户已存在"}
密码不在6-18位之间 返回结果{"code": 0, "msg": "账号和密码必须在6-18位之间"}
账号不在6-18位之间 返回结果{"code": 0, "msg": "账号和密码必须在6-18位之间"}
"""

View File

@ -0,0 +1,38 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/6 9:33
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import os
import unittest
from BeautifulReport import BeautifulReport
from python27Class.class03072020.demo1.testRegister import RegisterTestCase
"""
第一步创建测试套件并加载测试用例
"""
# 要执行的测试用例的位置
path = os.path.dirname(os.path.abspath(__file__))
suite = unittest.defaultTestLoader.discover(path)
"""
第二步执行测试套件中的用例 使用BeautifulReport生成HTML测试报告
2个参数报告描述用例名称报告文件名
report_dir用来指定报告的存放位置
"""
# 测试报告存放的路径
report_path = os.path.join(path, 'testReport')
b_report = BeautifulReport(suite)
b_report.report('Register Function Report by flora',
'register_beautiful_report.html',
report_dir=report_path
)

View File

@ -0,0 +1,30 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 9:47
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
from python27Class.class03072020.demo2.registerPage import register
from python27Class.class03072020.demo2.ddtNew import ddt, data
@ddt
class RegisterTestCase(unittest.TestCase):
cases = [
{'title': '该账户已存在', 'expect_result': {"code": 0, "msg": "该账户已存在"}, 'data': ['python26', '123456', '123456']},
{'title': '两次密码不一致', 'expect_result': {"code": 0, "msg": "两次密码不一致"}, 'data': ['python1', '12345655', '123456']},
]
@data(*cases)
def test_register(self, case):
# 参数准备
data = case['data']
# 预期结果准备
expect_result = case['expect_result']
# 获取实际结果
actual_result = register(*data)
# 断言
# assert expect_result == actual_result
self.assertEqual(expect_result, actual_result)

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,7 @@
pip install openpyxl
新建一个xlsx格式的excel将用例数据放在表格中
Excel的三大对象
workbook: 工作簿对象

View File

@ -0,0 +1,76 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 11:03
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import openpyxl
# 将指定的excel文件加载为一个workbook对象
wb = openpyxl.load_workbook('case.xlsx')
# 选中工作簿中的表单对象
sh = wb['case']
# # 读取指定格子中的数据
# c12 = sh.cell(row=1, column=2).value # 表示获取第一行第二列的数据
#
# # 写入数据
# sh.cell(row=3, column=1, value='flora')
# # 将工作簿对象保存为文件
wb.save('case.xlsx')
# 获取表单中的最大行
max_row = sh.max_row
print(max_row)
# 获取表单中的最大列
max_column= sh.max_column
print(max_column)
# rows按行获取整个表单里面的所有格子对象每行的内容放在一个元组中
"""
[(<Cell 'case'.A1>, <Cell 'case'.B1>,
<Cell 'case'.C1>, <Cell 'case'.D1>),
(<Cell 'case'.A2>, <Cell 'case'.B2>,
<Cell 'case'.C2>, <Cell 'case'.D2>)]
"""
res1 = list(sh.rows)
print(res1)
# 通过for循环获取每行中的内容
for item in res1:
for i in item:
print(i.value)
# columns按列获取整个表单里面的所有格子对象每行的内容放在一个元组中
"""
[(<Cell 'case'.A1>, <Cell 'case'.A2>),
(<Cell 'case'.B1>, <Cell 'case'.B2>),
(<Cell 'case'.C1>, <Cell 'case'.C2>),
(<Cell 'case'.D1>, <Cell 'case'.D2>)]
"""
res2 = list(sh.columns)
print(res2)
# 通过for循环获取每列中的内容
for item in res2:
for j in item:
print(j.value)
print('------------------')
# 读取第三行的数据
res3 = list(sh.rows)
print(res3[2])
for i in res3[2]:
print(i.value)
# 读取第二列到第四列的内容
res4 = list(sh.columns)
print(res4[1:3])
for j in res4[1:3]:
for i in j:
print(i.value)

View File

@ -0,0 +1,3 @@
本次课程的内容:
1. 将从excel读取用例数据的操作封装在一个readExcel的模块中
2. 执行测试的过程中将测试结果回写到excel中

View File

@ -0,0 +1,59 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/10 20:51
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import openpyxl
# 创建一个空列表,用来存放所有的用例数据
case_data = []
wb = openpyxl.load_workbook('cases.xlsx')
# 选择表单
sh = wb['register']
# 按行获取所有数据
datas = list(sh.rows)
# --------------单行数据打包------------------
# 获取第一行数据(表头), 保存到title这个列表中
# print(datas[0])
# title = []
# for item in datas[0]:
# print(item.value)
# title.append(item.value)
# # print(title)
#
# # 读取第二行
# values = []
# for item in datas[1]:
# values.append(item.value)
# # print(values)
#
# case = dict(zip(title, values))
# case_data.append(case)
# print(case_data)
# --------------------------------
# --------------多行数据打包------------------
# 获取第一行数据(表头), 保存到title这个列表中
print(datas[0])
title = []
for item in datas[0]:
title.append(item.value)
# 使用切片的方式,遍历除了第一行之外的行的数据
for item in datas[1:]:
# 每遍历出来一行数据就创建一个空列表来存放该行数据
values = []
# 遍历该行每个单元格的对象获取单元格中的数据值存放到values列表中
for i in item:
values.append(i.value)
# 每遍历完一行数据就拿该行的数据跟title表头打包转换为字典
case = dict(zip(title, values))
# 将该行用例数据追加到case_data列表中
case_data.append(case)
print(case_data)
# --------------------------------
# 注意从excel中读取出来的数据除了数值其他的不管保存的是什么格式读取出来的都是字符串。
# 读取出来的数据可以在使用的时候使用eval来转换一下。

Binary file not shown.

View File

@ -0,0 +1,319 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 10:52
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
# -*- coding: utf-8 -*-
# This file is a part of DDT (https://github.com/datadriventests/ddt)
# Copyright 2012-2015 Carles Barrobés and DDT contributors
# For the exact contribution history, see the git revision log.
# DDT is licensed under the MIT License, included in
# https://github.com/datadriventests/ddt/blob/master/LICENSE.md
import inspect
import json
import os
import re
import codecs
from functools import wraps
try:
import yaml
except ImportError: # pragma: no cover
_have_yaml = False
else:
_have_yaml = True
__version__ = '1.2.2'
# These attributes will not conflict with any real python attribute
# They are added to the decorated test method and processed later
# by the `ddt` class decorator.
DATA_ATTR = '%values' # store the data the test must run with
FILE_ATTR = '%file_path' # store the path to JSON file
UNPACK_ATTR = '%unpack' # remember that we have to unpack values
index_len = 5 # default max length of case index
try:
trivial_types = (type(None), bool, int, float, basestring)
except NameError:
trivial_types = (type(None), bool, int, float, str)
def is_trivial(value):
if isinstance(value, trivial_types):
return True
elif isinstance(value, (list, tuple)):
return all(map(is_trivial, value))
return False
def unpack(func):
"""
Method decorator to add unpack feature.
"""
setattr(func, UNPACK_ATTR, True)
return func
def data(*values):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
"""
global index_len
index_len = len(str(len(values)))
return idata(values)
def idata(iterable):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
"""
def wrapper(func):
setattr(func, DATA_ATTR, iterable)
return func
return wrapper
def file_data(value):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
``value`` should be a path relative to the directory of the file
containing the decorated ``unittest.TestCase``. The file
should contain JSON encoded data, that can either be a list or a
dict.
In case of a list, each value in the list will correspond to one
test case, and the value will be concatenated to the test method
name.
In case of a dict, keys will be used as suffixes to the name of the
test case, and values will be fed as test data.
"""
def wrapper(func):
setattr(func, FILE_ATTR, value)
return func
return wrapper
def mk_test_name(name, value, index=0):
"""
Generate a new name for a test case.
It will take the original test name and append an ordinal index and a
string representation of the value, and convert the result into a valid
python identifier by replacing extraneous characters with ``_``.
We avoid doing str(value) if dealing with non-trivial values.
The problem is possible different names with different runs, e.g.
different order of dictionary keys (see PYTHONHASHSEED) or dealing
with mock objects.
Trivial scalar values are passed as is.
A "trivial" value is a plain scalar, or a tuple or list consisting
only of trivial values.
"""
# Add zeros before index to keep order
index = "{0:0{1}}".format(index + 1, index_len)
if not is_trivial(value):
return "{0}_{1}".format(name, index)
try:
value = str(value)
except UnicodeEncodeError:
# fallback for python2
value = value.encode('ascii', 'backslashreplace')
test_name = "{0}_{1}_{2}".format(name, index, value)
return re.sub(r'\W|^(?=\d)', '_', test_name)
def feed_data(func, new_name, test_data_docstring, *args, **kwargs):
"""
This internal method decorator feeds the test data item to the test.
"""
@wraps(func)
def wrapper(self):
return func(self, *args, **kwargs)
wrapper.__name__ = new_name
wrapper.__wrapped__ = func
# set docstring if exists
if test_data_docstring is not None:
wrapper.__doc__ = test_data_docstring
else:
# Try to call format on the docstring
if func.__doc__:
try:
wrapper.__doc__ = func.__doc__.format(*args, **kwargs)
except (IndexError, KeyError):
# Maybe the user has added some of the formating strings
# unintentionally in the docstring. Do not raise an exception
# as it could be that user is not aware of the
# formating feature.
pass
return wrapper
def add_test(cls, test_name, test_docstring, func, *args, **kwargs):
"""
Add a test case to this class.
The test will be based on an existing function but will give it a new
name.
"""
setattr(cls, test_name, feed_data(func, test_name, test_docstring,
*args, **kwargs))
def process_file_data(cls, name, func, file_attr):
"""
Process the parameter in the `file_data` decorator.
"""
cls_path = os.path.abspath(inspect.getsourcefile(cls))
data_file_path = os.path.join(os.path.dirname(cls_path), file_attr)
def create_error_func(message): # pylint: disable-msg=W0613
def func(*args):
raise ValueError(message % file_attr)
return func
# If file does not exist, provide an error function instead
if not os.path.exists(data_file_path):
test_name = mk_test_name(name, "error")
test_docstring = """Error!"""
add_test(cls, test_name, test_docstring,
create_error_func("%s does not exist"), None)
return
_is_yaml_file = data_file_path.endswith((".yml", ".yaml"))
# Don't have YAML but want to use YAML file.
if _is_yaml_file and not _have_yaml:
test_name = mk_test_name(name, "error")
test_docstring = """Error!"""
add_test(
cls,
test_name,
test_docstring,
create_error_func("%s is a YAML file, please install PyYAML"),
None
)
return
with codecs.open(data_file_path, 'r', 'utf-8') as f:
# Load the data from YAML or JSON
if _is_yaml_file:
data = yaml.safe_load(f)
else:
data = json.load(f)
_add_tests_from_data(cls, name, func, data)
def _add_tests_from_data(cls, name, func, data):
"""
Add tests from data loaded from the data file into the class
"""
for i, elem in enumerate(data):
if isinstance(data, dict):
key, value = elem, data[elem]
test_name = mk_test_name(name, key, i)
elif isinstance(data, list):
value = elem
test_name = mk_test_name(name, value, i)
if isinstance(value, dict):
add_test(cls, test_name, test_name, func, **value)
else:
add_test(cls, test_name, test_name, func, value)
def _is_primitive(obj):
"""Finds out if the obj is a "primitive". It is somewhat hacky but it works.
"""
return not hasattr(obj, '__dict__')
def _get_test_data_docstring(func, value):
"""Returns a docstring based on the following resolution strategy:
1. Passed value is not a "primitive" and has a docstring, then use it.
2. In all other cases return None, i.e the test name is used.
"""
if not _is_primitive(value) and value.__doc__:
return value.__doc__
else:
return None
def ddt(cls):
"""
Class decorator for subclasses of ``unittest.TestCase``.
Apply this decorator to the test case class, and then
decorate test methods with ``@data``.
For each method decorated with ``@data``, this will effectively create as
many methods as data items are passed as parameters to ``@data``.
The names of the test methods follow the pattern
``original_test_name_{ordinal}_{data}``. ``ordinal`` is the position of the
data argument, starting with 1.
For data we use a string representation of the data value converted into a
valid python identifier. If ``data.__name__`` exists, we use that instead.
For each method decorated with ``@file_data('test_data.json')``, the
decorator will try to load the test_data.json file located relative
to the python file containing the method that is decorated. It will,
for each ``test_name`` key create as many methods in the list of values
from the ``data`` key.
"""
for name, func in list(cls.__dict__.items()):
if hasattr(func, DATA_ATTR):
for i, v in enumerate(getattr(func, DATA_ATTR)):
test_name = mk_test_name(name, getattr(v, "__name__", v), i)
# 将用例描述信息改为用例数据的title字段
# 原代码test_data_docstring = _get_test_data_docstring(func, v)
test_data_docstring = v['title']
if hasattr(func, UNPACK_ATTR):
if isinstance(v, tuple) or isinstance(v, list):
add_test(
cls,
test_name,
test_data_docstring,
func,
*v
)
else:
# unpack dictionary
add_test(
cls,
test_name,
test_data_docstring,
func,
**v
)
else:
add_test(cls, test_name, test_data_docstring, func, v)
delattr(cls, name)
elif hasattr(func, FILE_ATTR):
file_attr = getattr(func, FILE_ATTR)
process_file_data(cls, name, func, file_attr)
delattr(cls, name)
return cls

View File

@ -0,0 +1,107 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/10 20:11
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import openpyxl
# 需求: 将excel中的数据读取出来保存为以下格式
"""
[
{'title': '该账户已存在', 'expect_result': {"code": 0, "msg": "该账户已存在"}, 'data': ['python26', '123456', '123456']},
{'title': '两次密码不一致', 'expect_result': {"code": 0, "msg": "两次密码不一致"}, 'data': ['python1', '12345655', '123456']},
]
"""
# 封装的需求
"""
1. 封装一个读数据的功能
读数据需要用到什么 excel文件路径 表单名
2. 封装一个写入数据的方法
写数据需要用到哪些信息 文件表单写入内容
"""
class HandleExcel:
"""
用来操作excel文件的类
"""
def __init__(self, filename, sheetname):
"""
初始化对象属性
:param filename: 文件名
:param sheetname: 表单名
"""
self.filename = filename
self.sheetname = sheetname
def read_data(self):
"""
读取excel文件中的数据
:return:
"""
# 获取工作薄对象
wb = openpyxl.load_workbook(self.filename)
# 选择表单
sh = wb[self.sheetname]
# 按行获取所有数据,转换为列表
rows_data = list(sh.rows)
# 创建一个空列表,用来存放所有的用例数据
case_data = []
# 获取表单中第一行数据(表头), 保存到title这个列表中
title = []
for i in rows_data[0]:
title.append(i.value)
# 使用切片的方式,遍历除了第一行(表头)之外的行的数据
for item in rows_data[1:]:
# 每遍历出来一行数据就创建一个空列表来存放该行数据
values = []
# 遍历该行每个单元格的对象获取单元格中的数据值存放到values列表中
for i in item:
values.append(i.value)
# 每遍历完一行数据就拿该行的数据跟title表头打包转换为字典
case = dict(zip(title, values))
# 将该行用例数据追加到case_data列表中
case_data.append(case)
# --------------------------------
# 注意从excel中读取出来的数据除了数值其他的不管保存的是什么格式读取出来的都是字符串。
# 读取出来的数据可以在使用的时候使用eval来转换一下。
# 返回读取出来的所有数据
return case_data
def write_data(self, row, column, value):
"""
:param row:
:param column:
:param value: 写入的值
:return:
"""
# 获取工作簿对象
wb = openpyxl.load_workbook(self.filename)
# 选择表单
sh = wb[self.sheetname]
# 根据行列去写入内容
sh.cell(row=row, column=column, value=value)
# 把工作簿保存为文件
wb.save(self.filename)
if __name__ == '__main__':
excel = HandleExcel('cases.xlsx', 'register')
cases = excel.read_data()
print(cases)
excel1 = HandleExcel('cases.xlsx', 'testsheet')
excel1.write_data(1, 2, 'test')

View File

@ -0,0 +1,68 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/6 8:59
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
users = [{'user': 'python26', 'password': '123456'}]
def register(username, password1, password2):
"""
:param username:
:param password1:
:param password2:
:return:
"""
# 判断是否有参数为空
if not all([username, password1, password2]):
return {"code": 0, "msg": "所有参数不能为空"}
# 注册功能
for user in users: # 遍历出所有账号,判断账号是否存在
if username == user['user']:
# 账号存在
return {"code": 0, "msg": "该账户已存在"}
else:
if password1 != password2:
# 两次密码不一致
return {"code": 0, "msg": "两次密码不一致"}
else:
# 账号不存在 密码不重复,判断账号密码长度是否在 6-18位之间
if 6 <= len(username) >= 6 and 6 <= len(password1) <= 18:
# 注册账号
users.append({'user': username, 'password': password2})
return {"code": 1, "msg": "注册成功"}
else:
# 账号密码长度不对,注册失败
return {"code": 0, "msg": "账号和密码必须在6-18位之间"}
if __name__ == "__main__":
res = register('python14', '123456', '123456')
print(res)
"""
函数入参
注意参数传字符串类型不需要考虑其他类型
参数1账号
参数2密码1
参数2密码2
函数内部处理的逻辑
判断是否有参数为空
判断账号密码是否在6-18位之间
判断账号是否被注册过
判断两个密码是否一致
上面添加都校验通过才能注册成功其他情况都注册失败
各种情况的返回结果如下
注册成功 返回结果{"code": 1, "msg": "注册成功"}
有参数为空 返回结果 {"code": 0, "msg": "所有参数不能为空"}
两次密码不一致 返回结果{"code": 0, "msg": "两次密码不一致"}
账户已存在 返回结果{"code": 0, "msg": "该账户已存在"}
密码不在6-18位之间 返回结果{"code": 0, "msg": "账号和密码必须在6-18位之间"}
账号不在6-18位之间 返回结果{"code": 0, "msg": "账号和密码必须在6-18位之间"}
"""

View File

@ -0,0 +1,38 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/6 9:33
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import os
import unittest
from BeautifulReport import BeautifulReport
from python27Class.class03072020.demo1.testRegister import RegisterTestCase
"""
第一步创建测试套件并加载测试用例
"""
# 要执行的测试用例的位置
path = os.path.dirname(os.path.abspath(__file__))
suite = unittest.defaultTestLoader.discover(path)
"""
第二步执行测试套件中的用例 使用BeautifulReport生成HTML测试报告
2个参数报告描述用例名称报告文件名
report_dir用来指定报告的存放位置
"""
# 测试报告存放的路径
report_path = os.path.join(path, 'testReport')
b_report = BeautifulReport(suite)
b_report.report('Register Function Report by flora',
'register_beautiful_report.html',
report_dir=report_path
)

View File

@ -0,0 +1,43 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 9:47
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
from python27Class.class03102020.demo2.registerPage import register
from python27Class.class03102020.demo2.ddtNew import ddt, data
from python27Class.class03102020.demo2.readExcel import HandleExcel
@ddt
class RegisterTestCase(unittest.TestCase):
excel = HandleExcel('cases.xlsx', 'register')
cases = excel.read_data()
@data(*cases)
def test_register(self, case):
# 参数准备
data = eval(case['data'])
# 预期结果准备
expect_result = eval(case['expected'])
# 获取行号
row = case['case_id'] + 1
# 获取实际结果
actual_result = register(*data)
try:
# 断言
self.assertEqual(expect_result, actual_result)
except AssertionError as e:
# 断言不通过,引发断言异常
# 往excel写入结果未通过
self.excel.write_data(row=row, column=5, value='未通过')
# 主动抛出异常如果抛出异常unittest会判断该用例是执行通过的。
raise e
else:
# 断言通过执行else
# 往excel写入结果通过
self.excel.write_data(row=row, column=5, value='通过')

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
"""
=================================
Author: Flora Chen
2020/2/7 14:33
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
"""
1写一段代码运行的时候在控制台依次提示提示输入姓名年龄性别
最终在控制台按照以下格式输出图片省略
"""
name = input('请输入姓名:')
gender = input('请输入性别:')
age = input('请输入年龄:')
print('***************************')
print('姓名:', name)
print('性别:', gender)
print('年龄:', age)
print('***************************')
"""
2使用随机数模块生成一个5到10之间的浮点数输出到控制台
"""
import random
number = random.randint(5, 9) + random.random()
print('5到10之间的浮点数', number)
"""
3有5个数 a1=100a2 =300,a3=400b=180 c=1000,
要求一请使用逻辑运算符和比较运算符去 比较c大于 a1a2a3是否全部成立
要求二请使用逻辑运算符和比较运算符去 比较b大于 a1a2a3至少1个成立
"""
a1 = 100
a2 = 300
a3 = 400
b = 180
c = 1000
print('比较c大于 a1、a2、a3是否全部成立', (c > a1) and (c > a2) and (c > a3))
print('比较b大于 a1、a2、a3至少1个成立', (b > a1) or (b > a2) or (b > a3))
"""
4运算符的应用
1计算 5的三次方除以15的余数
2比较989除以57取余的结果是否大于17
"""
result = (5 ** 3) % 15
print('5的三次方除以15的余数', result)
result2 = 989 % 57
print('比较989除以57取余的结果是否大于17', result > 17)
"""
5总结上课笔记
******Python中常见的数据类型******
数值类型数据
1. 整数(int)例如a = 100
2. 小数(float)浮点数, 例如 b = 2.3
3. 布尔值(bool: True, False) 例如c= True, d = False
内置函数type()可以用来查看数据的类型
******Python中的运算符******
1. 算术运算符 + - * / //(向下取整) %(取余) **(幂运算)
2. 比较运算符== != > >= < <= 返回的是True或False
3. 赋值运算符= += -= *= /= *=
示例 a += 1 相当于a = a + 1
4. 逻辑运算符(用来比较2个条件)and() or() not() 返回的是True或False
and所有条件都成立返回True否则返回False一假为假 真真为真
or只要有一个条件成立返回True条件都不成立返回False一真为真假假为假
not 取反原来是True返回False; 原来是False返回True
5. 身份运算符(后面学)
6. 成员运算符(后面学)
******python中的内置随机函数random******
random.random()随机生成一个0-1之间的浮点数生成的小数范围是左闭右开包含0不包含1
random.randint()生成指定范围的整数包含起始位置和终止位置的值
import random
number = random.random()
number1 = random.randint(0, 100)
******字符串类型*****
1. 字符串可以通过单引号双引号三引号来表示
2. 单引号和双引号没有区别
3. 三引号可以用来表示多行字符串
******数据类型转换*****
整数和浮点数转换为字符串使用str
字符串和浮点数转换为整数使用int
整数和字符串转换为浮点数使用float
整数和浮点数字符串转换为布尔类型bool
注意点
使用字符串转换为int或float时字符串的内容必须是数字不能有字母和符号
整数和浮点数转布尔值只要不是0返回的布尔值都是True否则是False
字符串转布尔值空字符串(引号中没有任何内容包括空格或者其他标点符号)返回的布尔值是False其他都是True
扩展
按编码规范格式化代码的快捷键(pycharm)Ctrl + Alt + L
"""

View File

@ -0,0 +1,287 @@
"""
=================================
Author: Flora Chen
Time: 2020/2/8 8:13
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
"""
1现在有变量 a = hello , b = python18 c = ! ,通过相关操作转换成字符串'hello python18 !'注意点:转换之后单词之间有空格
"""
a = 'hello'
b = 'python18'
c = '!'
# 方法一:
print(a, b, c)
# 方法二:
print(a + ' ' + b + ' ' + c)
# 方法三:
print(' '.join((a, b, c)))
# 方法四:
print('{} {} {}'.format(a, b, c))
# 方法五:
print('%s %s %s' % (a, b, c))
# 方法六:
# print(F'{a} {b} {c}')
"""
2使用random模块和字符串拼接的方法随机生成一个130开头的手机号码只能使用上课学过的知识去做
"""
import random
print('手机号码130' + str(random.randint(1000000, 99999999)))
# 木森老师代码
#生成9位数
n = random.randint(10000000, 999999999)
# 切片取字符串的后8位
n1 = str(n)[1:]
phone = '130' + n1
print(phone)
"""
3有一个如下列表请编写代码提示用户输入1-7中的数字分别代表周一到周日根据用户输入打印输出今天是周X要求使用上课学过的知识点来做
li = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
"""
li = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
number = int(input('请输入1-7中的数字分别代表周一到周日'))
print('今天是' + li[number - 1])
"""
4现有字符串 str1 = "PHP is the best programming language in the world!"
要求一将给定字符串的PHP替换为Python
要求二替换以后将字符串以空格为分割点进行分割得到一个列表
"""
str1 = "PHP is the best programming language in the world!"
# 要求一
str2 = str1.replace('PHP', 'python')
print(str2)
# 要求二
li = str2.split(' ')
print(li)
"""
5切片操作
1通过切片获取s = 'python java php' 中的java
2通过切片获取 li = [2,3,1,4,6,2,5,6,7]中的 [2,5,6,7]
"""
s = 'python java php'
print(s[7:11])
print(s[-8:-4])
li = [2, 3, 1, 4, 6, 2, 5, 6, 7]
print(str(li[5:]))
print(str(li[-4:]))
"""
6整理笔记
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******字符串拼接******
1. 通过+对字符串进行拼接
示例
str1 = 'python'
str2 = 'hello'
print(str1 + str2) # 输出结果pythonhello
# 此种方法输出会在中间加空格
print(str1, str2) # 输出结果python hello
2. 使用字符串的join方法进行拼接
示例
str1 = 'python'
str2 = 'hello'
j = '---'
str3 = j.join((str1, str2))
print(str3) # 输出结果python---hello
或者
str1 = 'python'
str2 = 'hello'
str3 = ' '.join((str1, str2))
print(str3) # 输出结果python hello
或者
str1 = 'python'
str2 = ' '.join(str1)
print(str2) # 输出结果p y t h o n
******字符串格式化输出******
1. format格式化输出常用方式必须掌握
示例
str1 = '今天收到{} 交来{}{}。开此收据为凭证。'
str2 = str1.format('flora', '学杂费', 666)
print(str2) # 输出结果: 今天收到flora 交来学杂费666。开此收据为凭证。
print('今天收到{} 交来{}{}。开此收据为凭证。'.format('flora', '学杂费', 666))
通过索引来控制填充的位置
name = input('请输入名字:')
info = input('请输入费用信息:')
money = input('请输入金额:')
print('今天收到{2} 交来{1}费用{0}。开此收据为凭证。'.format(money, info, name))
保留指定小数位数
name = input('请输入名字:')
info = input('请输入费用信息:')
money = float(input('请输入金额:'))
print('今天收到{} 交来{}费用${:.2f}。开此收据为凭证。'.format(name, info, money))
指定占位的字符串长度
# 默认左对齐
print('python:{:10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果python:123 AAAAAAAAAAAAAAA
# 左对齐
print('python:{:<10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果python:123 AAAAAAAAAAAAAAA
# 右对齐
print('python:{:>10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果python: 123AAAAAAAAAAAAAAA
# 居中对齐
print('python:{:^10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果python: 123 AAAAAAAAAAAAAAA
指定内容填充
# 左对齐,以*填充
print('python:{:*<10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果123*******AAAAAAAAAAAAAAA
# 右对齐,以-填充
print('python:{:->10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果:-------123AAAAAAAAAAAAAAA
# 居中对齐,以@填充
print('python:{:@^10}AAAAAAAAAAAAAAA'.format('123'))
# 输出结果:@@@123@@@@AAAAAAAAAAAAAAA
百分比显示效果
print('百分比:{:.2%}'.format(0.89))
# 输出结果百分比89.00%
2. 传统的%格式化输出
%s万能占位符可以接收任意类型的数据
%d数值占位符以整数的形式显示
%f: 数值占位符以小数的形式显示
示例
print('今天收到%s 交来%s%d。开此收据为凭证。' % ('flora', '学杂费', 666.98))
# 输出结果: 今天收到flora 交来学杂费666。开此收据为凭证。
print('今天收到%s 交来%s%f。开此收据为凭证。' % ('flora', '学杂费', 666))
# 输出结果: 今天收到flora 交来学杂费666.000000。开此收据为凭证。
print('今天收到%s 交来%s%.2f。开此收据为凭证。' % ('flora', '学杂费', 666.909090))
# 输出结果今天收到flora 交来学杂费666.91。开此收据为凭证。
3. F表达式格式化输出
示例
name = input('请输入名字:')
info = input('请输入费用信息:')
money = input('请输入金额:')
print(F'今天收到{name} 交来{info}{money}。开此收据为凭证。')
******字符串转义******
反斜杠\表示转义
\t制表符tab键
\n换行符
\\表示1个反斜杠\
示例
print('python\thello')
# 输出结果python hello
print('python2\nhello2')
# 输出结果:
python2
hello2
关闭字符串转义r防转义
print(r'python\thello')
# 输出结果python\thello
print(r'python2\nhello2')
# 输出结果python2\nhello2
******字符串的常见操作方法******
1. count查找字符串中某个字符串的个数
示例
print('123aa123bb123cc123dd'.count('123'))
# 输出结果4
2. find查找字符串中某个字符串出现的第一个下标索引位置
示例
print('123aa123bb123cc123dd'.find('aa'))
# 输出结果3
3. replace替换字符串中的某个字符串默认替换所有
示例
print('123aa123bb123cc123dd'.replace('123', '*'))
# 输出结果:*aa*bb*cc*dd
# 可控制替换的次数
print('123aa123bb123cc123dd'.replace('123', '*', 1))
# 输出结果:*aa123bb123cc123dd
4. upper将字符串中的小写字母变成大写字母
示例
print('Hello World 132'.upper())
# 输出结果HELLO WORLD 132
5. lower将字符串中的大写字母变成小写字母
示例
print('Hello World 132'.lower())
# 输出结果hello world 132
6. split字符串分割
示例
# 以空格方式进行分割,返回的是个列表
print('Hello World 132'.split(' '))
# 输出结果:['Hello', 'World', '132']
# 使用join方法反向操作
print(' '.join(['Hello', 'World', '132']))
# 输出结果Hello World 132
******元组和列表******
列表和元组中可以保存多个数据可以是任意类型的每个元素之间用逗号隔开
元组tuple 用小括号来表示
tup = ('python', 66, 88.88, True, [11, 22, 33])
列表list 用中括号来表示
li = ['python', 66, 88.88, True, [11, 22, 33]]
扩展
序列类型的数据数据内部的元素是由顺序的有下标
序列类型的数据字符串列表元组
序列类型数据的共同特性
1. 可以通过下标取值通过下标获取数据内的元素
示例
# 正向取值从前往后数下标下标从0开始
print('python'[2]) # 输出结果t
print(['python', 66, 88.88, True, [11, 22, 33]][1]) # 输出结果66
print(('python', 66, 88.88, True, [11, 22, 33])[0]) # 输出结果python
# 反向取值:从后往前数下标,下标从-1开始
print('python'[-2]) # 输出结果o
print(['python', 66, 88.88, True, [11, 22, 33]][-1]) # 输出结果:[11, 22, 33]
print(('python', 66, 88.88, True, [11, 22, 33])[-3]) # 输出结果88.88
2. 可以通过切片操作获取数据中某一段数据[起始位置:终止位置] 左闭右开
示例
li = ['python', 66, 88.88, True, [11, 22, 33]]
print('[起始位置:终止位置] 左闭右开:', li[0:3])
# 输出结果:[起始位置:终止位置] 左闭右开: ['python', 66, 88.88]
"""

View File

@ -0,0 +1,288 @@
"""
=================================
Author: Flora Chen
Time: 2020/2/12 09:57
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
"""
现在有一个列表 li2=[12345]
第一步请通过三行代码将上面的列表改成这个样子 li2 = [0123665112233]
第二步对列表进行升序排序 从小到大
第三步将列表复制一份进行降序排序从大到小
"""
li2 = [1, 2, 3, 4, 5]
# 第一步
li2.extend([11, 22, 33])
li2.insert(0, 0)
li2[4] = 66
print('第一步:', li2)
# 第二步
li2.sort()
print('第二步:', li2)
# 第三步
li3 = li2.copy()
li3.sort(reverse=True)
print('第三步:', li2)
# 第三步或者可以这样
li3 = li2.copy()
li2.sort()
li2.reverse()
print('第三步:', li2)
"""
定义一个空列表user=[], 分别提示用户输入姓名年龄身高用户输入完之后将输入的信息作为添加的列表中保存然后按照以下格式输出
用户的姓名为xxx,年龄为xxx, 身高为xxx ,请仔细核对
"""
user = []
name = input('请输入姓名:')
age = input('请输入年龄:')
height = float(input('请输入身高:'))
user.extend([name, age, height])
print('用户的姓名为:{},年龄为:{}, 身高为:{:.2f} ,请仔细核对'.format(name, age, height))
"""
切片练习
1现在有一个字符串 s = 'abcdefghijk',
要求一通过切片获取: defg
要求二通过切片获取cgk
要求三通过切片获取jhf
"""
s = 'abcdefghijk'
# 要求一
print('通过切片获取: defg --', s[3:7])
print('通过切片获取: defg --', s[-8:-4])
# 要求二
print('通过切片获取: cgk --', s[2::4])
# 要求三
print('通过切片获取: jhf --', s[-2:-7:-2])
"""
2现在有一个列表li = [1,2,3,4,5,6,7,8,9] 请通过切片得出结果 [3,6,9]
"""
li = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print('通过切片得出结果 [3,6,9] --', li[2::3])
"""
整理笔记
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******列表切片******
可以通过切片操作获取数据中某一段数据
用法一 [起始位置:终止位置] 左闭右开
示例
li = ['python', 66, 88.88, True, [11, 22, 33]]
print('[起始位置:终止位置] 左闭右开:', li[0:3])
# 输出结果:[起始位置:终止位置] 左闭右开: ['python', 66, 88.88]
# 使用反向的下标进行切片
print(li[-2:-1]) # 输出结果:[True]
# 正向和反向下标可以混用
print(li[1:-2]) # 输出结果:[66, 88.88]
用法二[起始位置:终止位置:步长]
1. 步长为正数
示例
li = ['python', 66, 88.88, True, [11, 22, 33]]
# 默认步长为1默认打印整个列表
print(li[::]) # 输出结果: ['python', 66, 88.88, True, [11, 22, 33]]
# 步长为2 2个元素中取第一个元素。所以是1 3 5
print(li[::2]) # 输出结果: ['python', 88.88, [11, 22, 33]]
# 步长为3 3个元素中取第一个元素。所以是1 4
print(li[::3]) # 输出结果: ['python', True]
# 步长为4 4个元素中取第一个元素。所以是1 5
print(li[::4]) # 输出结果: ['python', [11, 22, 33]]
2. 步长设置为负数
示例
li = ['python', 66, 88.88, True, [11, 22, 33]]
# 步长为-1 是从后往前切片
print(li[::-1]) # 输出结果:[[11, 22, 33], True, 88.88, 66, 'python']
print(li[-1:-4:-1]) # 输出结果:[[11, 22, 33], True, 88.88]
******列表的常见操作方法******
列表list 用中括号[]来表示
列表可以保存多个数据可以是任意类型的每个元素之间用逗号隔开
列表可以转换成布尔值空列表li = []的布尔值为False其他的布尔值都是True
1. 内置函数len获取字符串列表元组字典集合的长度
示例
li = ['python', 66, 88.88, True, [11, 22, 33]]
print(len(li)) # 输出结果5
2. 新增列表元素
append(): 在列表尾部追加元素
示例
li = ['nancy', 'lily']
li.append('flora')
print(li) # 输出结果:['nancy', 'lily', 'flora']
insert(需要添加元素的下标位置 需要添加的元素)指定位置添加元素
示例
li = ['nancy', 'lily', 'flora']
li.insert(1, 'robot')
print(li) # 输出结果:['nancy', 'robot', 'lily', 'flora']
extend()一次性在列表尾部添加多个元素注意必须将需要添加的多个元素放在列表或者元组里面
示例
li = ['nancy', 'lily', 'flora']
li.extend(['jane', 'robot', 1, 2])
print(li) # 输出结果:['nancy', 'lily', 'flora', 'jane', 'robot', 1, 2]
3. 删除列表元素
remove(元素值)删除列表指定的元素
示例
li = ['nancy', 'lily', 'flora']
li.remove('lily')
print(li) # 输出结果:['nancy', 'flora']
pop()通过下标删除指定的元素默认删除最后一个
示例
li = ['nancy', 'lily', 'flora', 'robot', 'jane']
li.pop()
print(li) # 输出结果:['nancy', 'lily', 'flora', 'robot']
li.pop(1)
print(li) # 输出结果:['nancy', 'flora', 'robot']
clear()清空列表(删除列表中的所有元素)
示例
li = ['nancy', 'lily', 'flora', 'robot', 'jane']
li.clear()
print(li) # 输出结果:[]
4. 查看列表元素
通过下标取值
示例
li = ['nancy', 'lily', 'flora', 'robot', 'jane']
# 通过下标取值查找元素
print(li[1]) # 输出结果lily
index()查找元素的下标值找到第一个就返回不会继续再查找如果元素不存在会报错
示例
li = ['nancy', 'lily', 'flora', 'robot', 'jane', 'flora', 'miya', 'apple']
index = li.index('flora')
print(index) # 输出结果2
# 在指定范围内查找元素的下标值,左闭右开
index = li.index('flora', 3, 6)
print(index) # 输出结果5
count():查找列表中某个元素的个数
示例
li = ['nancy', 'lily', 'flora', 'robot', 'jane', 'flora', 'miya', 'apple']
print(li.count('flora')) # 输出结果2
5. 修改列表元素
通过下标赋值
示例
li = ['nancy', 'lily', 'flora', 'robot', 'jane', 'flora', 'miya', 'apple']
li[1] = 11
print(li) # 输出结果:['nancy', 11, 'flora', 'robot', 'jane', 'flora', 'miya', 'apple']
6. 列表的其他方法
sort()对列表进行排序列表中全是数值类型如果列表中全是字符串是按照ASCII值进行排序的
示例
li = [11, 2, 353, 44, 88, 99, 123]
li.sort() # 默认从小到大排序, reverse默认为False
print(li) # 输出结果:[2, 11, 44, 88, 99, 123, 353]
li.sort(reverse=True) # 从大到小排序
print(li) # 输出结果:[353, 123, 99, 88, 44, 11, 2]
reverse()将列表反向从末尾到起始排序
示例
li = [11, 2, 353, 44, 88, 99, 123]
li.reverse() # 此操作相当于 li[::-1]
print(li) # 输出结果:[123, 99, 88, 44, 353, 2, 11]
copy()复制
示例
li = [1, 2, 3, 4, 5, 6, 7]
# 变量赋值引用的是li中的数据
li2 = li
print(id(li)) # 输出结果2144668143360
print(id(li2)) # 输出结果2144668143360
# 在列表类li2中追加元素同样会作用到li中
li2.append(9)
print(li) # 输出结果:[1, 2, 3, 4, 5, 6, 7, 9]
print(li2) # 输出结果:[1, 2, 3, 4, 5, 6, 7, 9]
# 复制
li3 = li.copy()
print(id(li3)) # 输出结果2814574980480
print(li is li3) # 输出结果False
# 在列表类li3中追加元素不会影响li
li3.append(80)
print(li) # 输出结果:[1, 2, 3, 4, 5, 6, 7, 9]
print(li3) # 输出结果:[1, 2, 3, 4, 5, 6, 7, 9, 80]
******运算符补充******
身份运算符is, is not比较2个数据是否引用的是同一个对象比较id内存地址是否一致
示例
li = [11, 2, 353, 44]
li2 = [11, 2, 353, 44]
li3 = li
# 内置函数id查看数据的内存地址
print(id(li)) # 输出结果1792807521984
print(id(li2)) # 输出结果1792807540928
print(id(li3)) # 输出结果1792807521984
print(li is li2) # 输出结果False
print(li is li3) # 输出结果True
print(li is not li3) # 输出结果False
扩展
在python中 -5 256 之间的数据小整数池内存地址都是一样的
# 在终端运行
a = -5
b = -5
print(id(a)) # 输出结果140706950989280
print(id(b)) # 输出结果140706950989280
a = -6
b = -6
print(id(a)) # 输出结果1739394026288
print(id(b)) # 输出结果1739394026352
成员运算符in, not in判断某个元素是否存在于列表中
示例
li = [1, 2, 3, 4, 5, 6, 7]
zs = 1
ls = 8
# 判断zs, ls是否存在于列表中
print(zs in li) # 输出结果True
print(ls in li) # 输出结果False
# 判断zs, ls是否不存在于列表中
print(zs not in li) # 输出结果False
print(ls not in li) # 输出结果True
******元组******
元组tuple 用小括号来表示
元组的方法只有查询的方法没有添加元素修改元素删除元素的方法
1. 通过下标取值
index()查找元素的下标值找到第一个就返回不会继续再查找如果元素不存在会报错
示例
tup = (1, 2, 33, 4, 5, 6, 33, 44, 33, 7)
print(tup[2]) # 输出结果33
print(tup.index(33)) # 输出结果2
print(tup.index(33, 3, 8)) # 输出结果6
2. count():查找列表中某个元素的个数
示例
tup = (1, 2, 33, 4, 5, 6, 33, 44, 33, 7)
print(tup.count(33)) # 输出结果3
"""

View File

@ -0,0 +1,191 @@
"""
=================================
Author: Flora Chen
Time: 2020/2/13 19:49
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
"""
1 将字符串中的单词位置反转hello xiao mi 转换为 mi xiao hello
提示通过字符串分割拼接列表反序等知识点来实现
"""
str1 = 'hello xiao mi'
str_list = str1.split(' ')
str_list.reverse()
# 如果是直接打印 这样就可以了
print('{} {} {}'.format(str_list[0], str_list[1], str_list[2]))
# 但是如果要变成一个新的变量,增加如下操作
new_str = ' '.join(str_list)
# new_str = ' '.join((str_list[0], str_list[1], str_list[2]))
print(new_str)
new_str2 = '{} {} {}'.format(str_list[0], str_list[1], str_list[2])
print(new_str2 )
"""
2字典的增删查改操作 某比赛需要获取你的个人信息编写一段代码要求如下
1运行时分别提醒输入 姓名性别年龄 输入完了请将数据通过字典存储起来
2数据存储完了然后输出个人介绍格式如下: 我的名字XXX今年XXX岁性别XX喜欢敲代码
3有一个人对你很感兴趣平台需要您补足您的身高和联系方式
4平台为了保护你的隐私需要你删除你的联系方式
5你为了取得更好的成绩 你添加了一项自己的擅长技能
"""
# 1
name = input('请输入您的姓名:')
gender = input('请输入您的性别:')
age = input('请输入您的年龄:')
info = {'name': name, 'gender': gender, 'age': int(age)}
# 2
print('我的名字{},今年{}岁,性别{},喜欢敲代码'.format(info['name'], info['age'], info['gender']))
# 3
height = input('请输入您的身高:')
phone = input('请输入您的联系方式:')
info.update({'height': float(height), 'phone': phone})
print('我的名字{},今年{}岁,性别{},身高{:.2f},联系方式{},喜欢敲代码;'.format(info['name'], info['age'], info['gender'], info['height'], info['phone']))
# 4
info.pop('phone')
print('我的名字{},今年{}岁,性别{},身高{:.2f},喜欢敲代码;'.format(info['name'], info['age'], info['gender'], info['身高']))
# 5
skill = input('请输入您擅长的技能:')
info['skill'] = skill
print('我的名字{},今年{}岁,性别{},身高{:.2f},擅长{},喜欢敲代码;'.format(info['name'], info['age'], info['gender'], info['height'], info['skill']))
"""
3利用下划线将列表li=[python,java,php]的元素拼接成一个字符串然后将所有字母转换为大写
"""
li = ['python', 'java', 'php']
# 方法一
str_li = li[0] + '_'+ li[1] + '_' + li[2]
# 方法二
str_li2 = '_'.join(li)
# str_li2 = '_'.join((li[0], li[1], li[2]))
print('方法一:', str_li.upper())
print('方法二:', str_li2.upper())
"""
4利用切片把 'http://www.python.org'中的python字符串取出来
"""
url = 'http://www.python.org'
# 方法一
print(url[11:17])
# 方法二
print(url[-10:-4])
"""
5编写一个买橘子的计算器
运行代码提示输入橘子的价格要考虑小数的情况
然后随机生成斤数1-100之间整数最后计算应付金额控制台输出如下信息(所有数据输出时都要保留两位小数)
输出内容格式您购买的橘子为xx.xx斤每斤xx.xx元应支付金额为xx.xx
"""
import random
orange_price = float(input('请输入橘子的价格:'))
weight = random.randint(1, 100)
total_price = orange_price * weight
print('您购买的橘子为{:.2f}斤,每斤{:.2f}元,应支付金额为{:.2f}'.format(weight, orange_price, total_price))
"""
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******字典dict******
1. 字典的定义
花括号{}表示字典字典中的元素是由键值(key:value)对组成的每个元素用逗号隔开
字典是没有下标索引的其键key就是索引
示例
dic = {}
dict2 = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
print(type(dic)) # 输出结果:<class 'dict'>
print(dict2) # 输出结果:{'name': 'flora', 'age': 18, 'phone': '10220020200'}
print(dict2['name']) # 输出结果flora
2. 字典中的相关规范
字典中的键不能重复
字典中的键只能使用不可变类型字符串数值类型元组的数据通常是用字符串
字典中的值可以是任何数据类型
扩展
不可变类型的数据数值类型字符串元组
可变类型的数据列表字典集合
3. 字典的相关操作
添加一个元素
示例
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
dic['height'] = 156
print(dic)
# 输出结果:{'name': 'flora', 'age': 18, 'phone': '10220020200', 'height': 156}
添加多个元素
示例
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
dic.update({'height': 156, 'heavy': '56kg'})
print(dic)
# 输出结果:{'name': 'flora', 'age': 18, 'phone': '10220020200', 'height': 156, 'heavy': '56kg'}
修改元素:键已存在就是修改否则是新增
示例
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
dic['phone'] = '18956423668'
print(dic)
# 输出结果:{'name': 'flora', 'age': 18, 'phone': '18956423668'}
删除元素
pop()通过键去删除指定的键值对返回键对应的值
示例
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
res = dic.pop('phone')
print(res) # 输出结果10220020200
print(dic)
# 输出结果:{'name': 'flora', 'age': 18}
popitem()删除最后添加进去的键值对,以元组的形式返回一个键值对
示例
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
res = dic.popitem()
print(res) # 输出结果:('phone', '10220020200')
print(dic)
# 输出结果:{'name': 'flora', 'age': 18}
查找元素
通过键进行索引取值键不存在会报错
示例
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
res = dic['phone']
print(res) # 输出结果10220020200
get()通过键获取对应的值键不存在不会报错但是会返回None
示例
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
res = dic.get('phone')
print(res) # 输出结果10220020200
res2 = dic.get('heg') #键不存在
print(res2) # 输出结果None
获取字典中的所有键所有值所有键值对
keys()获取字典中所有的键
示例
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
print(dic.keys()) # 输出结果dict_keys(['name', 'age', 'phone'])
print(list(dic.keys())) # 可通过list()转换成列表
# 输出结果:['name', 'age', 'phone']
values()获取字典中所有的值
示例
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
print(dic.values()) # 输出结果dict_values(['flora', 18, '10220020200'])
print(list(dic.values())) # 可通过list()转换成列表
# 输出结果:['flora', 18, '10220020200']
items()获取字典中所有的键值对
示例
dic = {'name': 'flora', 'age': 18, 'phone': '10220020200'}
print(dic.items()) # 输出结果dict_items([('name', 'flora'), ('age', 18), ('phone', '10220020200')])
print(list(dic.items())) # 可通过list()转换成列表
# 输出结果:[('name', 'flora'), ('age', 18), ('phone', '10220020200')]
"""

View File

@ -0,0 +1,362 @@
"""
======================================
Author: Flora.Chen
Time: 2020/2/15 13:03
~ _ ~ ~ _ ~ ~ _ ~ ~ _ ~ ~ _ ~ ~ _ ~
======================================
"""
"""
请获取下面数据中的token和reg_name
data = {
"code": 0,
"msg": "OK",
"data": {
"id": 74711,
"leave_amount": 29600.0,
"mobile_phone": "13367899876",
"reg_name": "小柠檬666",
"reg_time": "2019-12-13 11:12:53.0",
"type": 0,
"token_info": {
"token_type": "Bearer",
"expires_in": "2019-12-30 22:28:57",
"token": "eyJhbGciOiJIUzUxMiJ9.eyJtZW1iZXJfaWQiOjc0NzExLCJleHAiOjE1Nzc3MTYxMzd9.eNMtnEWr57iJoZRf2IRsGDWm2GKj9LZc1J2SGRprAwOk7EPoJeXSjJwdh0pcVVJygHmsbh1TashWqFv1bvCVZQ"
}
},
"copyright": "Copyright 柠檬班 © 2017-2019 湖南省零檬信息技术有限公司 All Rights Reserved"
}
"""
data = {
"code": 0,
"msg": "OK",
"data": {
"id": 74711,
"leave_amount": 29600.0,
"mobile_phone": "13367899876",
"reg_name": "小柠檬666",
"reg_time": "2019-12-13 11:12:53.0",
"type": 0,
"token_info": {
"token_type": "Bearer",
"expires_in": "2019-12-30 22:28:57",
"token": "eyJhbGciOiJIUzUxMiJ9.eyJtZW1iZXJfaWQiOjc0NzExLCJleHAiOjE1Nzc3MTYxMzd9.eNMtnEWr57iJoZRf2IRsGDWm2GKj9LZc1J2SGRprAwOk7EPoJeXSjJwdh0pcVVJygHmsbh1TashWqFv1bvCVZQ"
}
},
"copyright": "Copyright 柠檬班 © 2017-2019 湖南省零檬信息技术有限公司 All Rights Reserved"
}
token = data['data']['token_info']['token']
reg_name = data['data']['reg_name']
print(token)
print(reg_name)
"""
有下面几个数据 t1 = ("aa",11) t2= (''bb'',22) li1 = [("cc",22)]
请通过学过的知识点进行相关操作变为如下字典: {"aa":11,"cc":22,"bb":22}
"""
t1 = ('aa', 11)
t2 = ('bb', 22)
li1 = [('cc', 22)]
# 先将元祖t1 t2添加到列表li1中
li1.insert(0, t1)
li1.append(t2)
# 再将列表转换成字典
dic1 = dict(li1)
# 打印字典
print(dic1)
"""
当前有一个列表 li = [11,22,33,22,22,44,55,77,88,99,11]
要求一去除列表中的重复元素
要求二去重后删除 778899这三个元素
"""
li = [11, 22, 33, 22, 22, 44, 55, 77, 88, 99, 11]
# 要求一:去除列表中的重复元素
set1 = set(li)
print(set1)
# 要求二:去重后删除 778899这三个元素
new_li = list(set1)
new_li.remove(77)
new_li.remove(88)
new_li.remove(99)
print(new_li)
"""
利用random函数生成随机整数范围1-9然后用户输入一个数字来进行比较
如果大于随机数则打印印大于随机数
如果小于随机数则打印小于随机数
如果相等随机数则打印等于随机数
"""
import random
random_number = random.randint(1, 9)
input_number = int(input('请输入一个数字:'))
if input_number > random_number:
print('大于随机数')
elif input_number < random_number:
print('小于随机数')
else:
print('等于随机数')
"""
一家商场在降价促销如果购买金额50-100(包含50元和100元)之间会给打九折
如果购买金额大于100元会给打八折编写一程序询问购买价格再打印出折扣和最终价格
"""
price = float(input('请输入你购买的价格:'))
price = int(price)
if price <= 0:
print('输入有误!')
elif 0 < price < 50:
cost = int(price * 0.9)
print('商品打9折最终价格为{}'.format(cost))
elif 50 <= price <= 100:
print('商品不打折!')
else:
cost = int(price * 0.8)
print('商品打8折最终价格为{}'.format(cost))
"""
提示用户输入一个数只考虑整数判断这个数能同时被3和5整除
能整除打印 :这个数据我喜欢
不能整除打印这个数据不太喜欢
"""
number = int(input('请输入与一个数:'))
if (number % 5 == 0) and (number % 3 == 0):
print('这个数据我喜欢')
else:
print('这个数据不太喜欢')
"""
整理笔记
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******集合******
1. 集合的定义
集合 set类型 通过{}来表示
内部的数据{value, value1, value2}
示例
set1 = {11, 22, 33, 44, 55}
print(type(set1)) # 输出结果:<class 'set'>
2. 集合的特性
集合的数据不能存在重复的元素
集合中的数据只能是不可变类型数值类型字符串元组
集合和字典都是无序的没有下标索引
集合是可变类型的数据
集合的操作
add: 添加数据
pop删除数据
示例
set1 = {11, 22, 33, 44, 55, 55}
print(set1) # 输出结果:{33, 11, 44, 22, 55}
set1.add(678)
print(set1) # 输出结果:{33, 678, 11, 44, 22, 55}
set1.pop() # 随机删除一个元素
print(set1) # 输出结果:{678, 11, 44, 22, 55}
3. 集合的应用
对数据的去重
示例
# 对字符串去重
str1 = 'dfgdfghjkhjk'
s1 =set(str1)
print(s1) # 输出结果:{'d', 'k', 'f', 'j', 'g', 'h'}
# 对列表去重
li = [11, 11, 22, 22, 33]
s1 =set(li)
print(list(s1)) # 输出结果:[33, 11, 22]
用来区分数据是否可变
# 运行不报错的就都是不可变类型的:数值类型,字符串,元组
set1 = {111, 12.33, '243', True, (1, 2)}
# 运行报错的就都是可变类型的:列表,字典,集合
# set2 = {[1, 2, 3]} # TypeError: unhashable type: 'list'
# set3 = {{'name': 'flora'}} # TypeError: unhashable type: 'dict'
set4 = {{1,2,3}} # TypeError: unhashable type: 'set'
******数据类型总结******
1. 按数据结构分类
数值类型整数浮点数布尔值
序列类型字符串列表元组可以通过下标取值支持切片操作
散列类型字典集合元素内部是无序的没有下标
2. 数据类型的可变与不可变
不可变类型数值类型字符串元组
字符串和元组定义之后不能修改内部结构或者值内存单元中的值为不可变类型
可变类型列表字典集合
如何区分可变不可变数据定义一个集合把数据放到集合中看会不会报错会报错的是可变类型
******控制流******
顺序代码从上往下执行
分支根据不同的条件执行不同的代码
循环特定的代码重复执行
注意python中通过缩进来区分代码块的
******条件判断******
1. if语句
if 条件
# 条件成立执行的代码块
示例
# 用户输入考试成绩,请判断是否及格。
score = float(input('请输入您的成绩:'))
if score >= 60:
# 条件成立执行的代码块
print('考试及格!')
2. if - else语句
if 条件
# 条件成立执行的代码块
else:
# 条件不成立执行的代码块
示例
# 用户输入考试成绩,请判断是否及格。如果考试不及格,打印:考试不及格,晚上通宵敲代码!
score = float(input('请输入您的成绩:'))
if score >= 60:
# 条件成立执行的代码块
print('考试及格!')
else:
# 条件不成立执行的代码块
print('考试不及格,晚上通宵敲代码!')
3. if - elif - else语句
if 条件1
# 条件成立执行的代码块
elif 条件2
# 条件2成立执行的代码块
elif 条件3
# 条件3成立执行的代码块
else:
# 以上条件均不成立执行的代码块
# 用户输入考试成绩根据不同等级进行区分A 90分以上 B80-90分 C 60-80分 D60分以下
score = int(input('请输入您的成绩:'))
if 0 <= score < 60:
print('您的成绩为D')
elif 60 <= score < 80:
print('您的成绩为C')
elif 80 <= score < 90:
print('您的成绩为B')
elif 90 <= score < 100:
print('您的成绩为A')
else:
print('您输入的成绩有误!')
4. 多个条件同时判断
# 登录小案例:事先存储一组账号密码,提示用户输入账号和密码,然后判断账号密码是否输入正确
user_info = {'user': 'flora', 'pwd': '123455555Az'}
username = input('请输入账号:')
passwd = input('请输入密码:')
# 方式一:使用嵌套方式
if username == user_info['user']:
if passwd == user_info['pwd']:
print('账号密码输入正确!')
else:
print('密码输入不正确!')
else:
print('账号输入不正确!')
# 方式二:使用逻辑运算符去判断多个条件
if username == user_info['user'] and passwd == user_info['pwd']:
print('账号密码输入正确!登录成功!')
else:
print('账号或密码输入不正确!登录失败!')
总结
使用if开启一个条件判断语句
一个条件语句中只有一个if但是一个条件语句中可以有多个或者一个或者零个elif;
一个条件语句中只有一个或者零个else
if判断成立的标准
if成立的标准是根据if后面的python表达式或者数据的布尔值是否为True来确定条件是否成立
******python中数据的布尔值******
非0位TrueNone 数字0或者数据长度为0len()的布尔值为False 其他数据布尔值都是True
数据长度为0 例如空字符串空列表空元祖空字典
示例:
str1 = 'python'
li = [1, 2, 2]
if li:
print('成立!')
else:
print('不成立!')
******while循环(条件循环)******
1. while循环的使用
如果条件一直成立则一直循环做条件满足的事情直到条件不成立结束循环
while 条件
# 条件成立,循环执行的代码块
# 条件成立,循环执行的代码块
# 条件成立,循环执行的代码块
# ......
示例
# 创建一个变量来保存循环的次数
i = 0
while i < 5:
print('hello python')
i += 1 # i = i + 1
# 输出结果:
# hello python
# hello python
# hello python
# hello python
# hello python
2. 死循环以及相关案例的使用
死循环循环的条件一直成立在循环体中无限循环称之为死循环
避免写代码的过程中因为逻辑问题造成代码死循环
示例
while True:
print('hello python')
3. break强制跳出循环
死循环在特定的需求下我们也会使用再循环内部要实现跳出循环的机制合理使用break
示例
while True:
user_info = {'user': 'flora', 'pwd': '123455555Az'}
username = input('请输入账号:')
passwd = input('请输入密码:')
if username == user_info['user'] and passwd == user_info['pwd']:
print('账号密码输入正确!登录成功!')
break
else:
print('账号或密码输入不正确!请重新输入!')
4. 循环内嵌套条件语句
示例
# 打印3次之后强制退出循环
i = 0
while i < 5:
print('hello python')
i += 1 # i = i + 1
# 当i=3时退出循环
if i == 3:
break
5. continue终止本轮循环直接进行下次循环的条件判断
示例
# 第5-7次不打印
i = 0
while i < 10:
i += 1 # i = i + 1
# 当i在5~7之间则执行continue终止本轮循环进行下轮循环的条件判断
if 5 <= i <= 7:
continue
print('hello python')
"""

View File

@ -0,0 +1,331 @@
"""
=================================
Author: Flora Chen
Time: 2020/2/18 19:45
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
"""
1输出99乘法表结果如下提示嵌套for循环参照上课打印三角形的案例
"""
for i in range(1, 10):
for j in range(1, i + 1):
print('{} * {} = {}\t'.format(i, j, i * j), end='')
print()
"""
2实现剪刀石头布游戏提示用户输入要出的拳 石头1剪刀23/退出4 电脑随机出拳比较胜负显示 用户胜负还是平局
运行如下图所示提示while循环加条件判断做判断时建议先分析胜负的情况
"""
# musen老师代码
import random
print('---石头剪刀布游戏开始---')
print('请按照下面的提示出拳:')
li = ['石头', '剪刀', '']
while True:
print('石头【1】剪刀【2】布【3】/结束游戏【4】')
user_num = int(input('请输入你的选项:'))
r_num = random.randint(1, 3)
print(r_num)
if 1 <= user_num <= 3:
if r_num == user_num:
print('您的出拳为:{} 电脑出拳:{},平局'.format(li[user_num - 1], li[r_num - 1]))
elif (user_num - r_num) == -1 or (user_num - r_num) == 2:
print('您的出拳为:{} 电脑出拳:{},您胜利了'.format(li[user_num - 1], li[r_num - 1]))
else:
print('您的出拳为:{} 电脑出拳:{},您输了'.format(li[user_num - 1], li[r_num - 1]))
elif user_num == 4:
print('游戏结束!')
break
else:
print('您出拳有误,请按规矩出拳!')
# --------------------------------------------------------------------------
while True:
print('---石头剪刀布游戏开始---')
print('请按照下面的提示出拳:\n石头【1】剪刀【2】布【3】/结束游戏【4】')
user_hand = int(input('请输入你的选项:'))
# 根据用户输入的数字,输出用户出拳的象征
if user_hand == 1:
user_icon = '石头'
print('用户出的是:', user_icon)
elif user_hand == 2:
user_icon = '剪刀'
print('用户出的是:', user_icon)
elif user_hand == 3:
user_icon = ''
print('用户出的是:', user_icon)
elif user_hand == 4:
print('游戏结束!')
break
else:
print('您出拳有误,请按规矩出拳!')
# 根据系统随机输出的数字,输出系统出拳的象征
system_hand = random.randint(1, 3)
if system_hand == 1:
system_icon = '石头'
print('系统出的是:', system_icon)
elif system_hand == 2:
system_icon = '剪刀'
print('系统出的是:', system_icon)
elif system_hand == 3:
system_icon = ''
print('系统出的是:', system_icon)
# 根据用户以及系统的出拳,决定胜负
if ((user_hand == 1) and (system_hand == 2)) or ((user_hand == 2) and (system_hand == 3)) or (
(user_hand == 3) and (system_hand == 1)):
print('您的出拳为:{} 电脑出拳:{},您胜利了\n'.format(user_icon, system_icon))
elif user_hand == system_hand:
print('您的出拳为:{} 电脑出拳:{},平局\n'.format(user_icon, system_icon))
else:
print('您的出拳为:{} 电脑出拳:{},您输了\n'.format(user_icon, system_icon))
"""
3通过定义一个计算器函数调用函数分别提示用户输入数字1数字2然后再提示用户选择 1 2 3 4
根据不同的选择完成不同的计算 然后打印结果提示函数中加条件判断
"""
def calculate():
print('欢迎使用计算器!')
num1 = int(input('请输入数字1'))
num2 = int(input('请输入数字2'))
cal_way = int(input('请选择计算方式加【1】 减【2】 乘【3】 除【4】'))
if cal_way == 1:
return num1 + num2
elif cal_way == 2:
return num1 - num2
elif cal_way == 3:
return num1 * num2
elif cal_way == 4:
return num1 / num2
else:
return print('您的输入有误')
print('结果是:', calculate())
"""
5扩展练习题不用提交不计入评分有时间的同学可以做
学习控制流程时我们讲了一个登录的案例现在要求大家通过代码实现一个注册的流程基本要求
1运行程序提示用户输入用户名输入密码再次确认密码
2判读用户名有没有被注册过如果用户名被注册过了那么打印结果该用户名已经被注册
3用户名没有被注册过则判断两次输入的密码是否一致一致的话则注册成功否则给出对应的提示
4下面是已注册的两个账户注册成功的账号密码按下面的形式保存到列表users中
users = [{"uaer":"py27","pwd":"lemonban"},{"uaer":"py28","pwd":"lemonban2"}]
提示要是有for-else语句才能实现
"""
# 运行程序,提示用户,输入用户名,输入密码,再次确认密码
username = input('请输入用户名:')
passwd = input('请输入密码:')
passwd_confirm = input('请再次输入密码:')
# 已有的用户列表
users = [{'user': 'py27', 'pwd': 'lemonban'}, {'user': 'py28', 'pwd': 'lemonban2'}]
# 循环遍历用户列表
for items in users:
# 判断用户名是否已注册,已注册就提示用户已注册,并且终止循环
if username == items['user']:
print('该用户名已经被注册:', username)
break
# 用户名未注册,就判断用户两次输入的密码是否一致
else:
# 如果一致就将用户信息添加到已有用户列表,并提示用户注册成功
if passwd == passwd_confirm:
users.append({'user': username, 'pwd': passwd})
print('恭喜你!注册成功', users)
# 如果不一致就提示用户两次输入的密码不一致
else:
print('两次输入的密码不一致!')
"""
4整理笔记
=================================
Notes
Author: Flora Chen
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
******for循环******
1. 定义
for i in xxx:
# 循环体
2. 遍历字符串
示例
str1 = 'flora'
for i in str1:
print(i)
3. 遍历列表
示例
# 当前有10位同学的成绩在一个列表中请区分成绩的等级
li = [90, 78, 56, 89, 65, 80, 74, 34, 89, 100]
for score in li:
if 0 < score < 60:
print('成绩{}:不及格'.format(score))
elif 60 <= score < 80:
print('成绩{}:及格'.format(score))
elif 80 <= score < 90:
print('成绩{}:优秀'.format(score))
else:
print('成绩{}:非常优秀'.format(score))
4. 遍历字典
示例
dic1 = {'name': 'flora', 'gender': 'girl', 'age': 18}
for i in dic1.keys():
print('遍历字典的键:', i)
for i in dic1.values():
print('遍历字典的值:', i)
for i in dic1.items():
print('遍历字典的键值对:', i)
# 遍历字典键值对时用2个变量分别保存键和值。
# for i in dic1.items():
# k, v = i
# print('遍历字典的键:', k)
# print('遍历字典的值:', v)
for k, v in dic1.items():
print('遍历字典的键:', k)
print('遍历字典的值:', v)
5. for循环中的break, continue
示例
# 需求一打印10遍hello python
for i in range(1, 11):
print('1: 这是第{}遍: hello python'.format(i))
# 需求二打印到第50遍跳出循环
for i in range(1, 11):
print('2: 这是第{}遍: hello python'.format(i))
if i == 5:
break
# 需求三第3~5遍不打印
for i in range(1, 11):
if 3 <= i <= 5:
continue
print('3这是第{}遍: hello python'.format(i))
6. for循环中的高级语法for -- else
for对应的else语句只有当循环是通过break结束的时候不会执行其他情况下都会执行
示例
for i in range(10):
print('本轮遍历的数据为{}'.format(i))
else:
print('for对应的else语句')
示例
users = [{'user': 123}, {'user': 122}, {'user': 124}]
user = input('请输入您的账号:')
for i in users:
if user == str(i['user']):
print('用户已存在!')
break
else:
print('用户不存在!')
# 缺陷输入1111会打印3遍用户不存在
for i in users:
if user == str(i['user']):
print('用户已存在!')
break
else:
print('用户不存在!')
******内置函数range()******
range(n) 默认生成0 ~ n-1的整数序列对于这个序列我们可以通过list()转化为列表类型的数据
range(n, m)左闭右开默认生成从n ~ m-1的整数序列 对于这个序列我们可以通过list()转化为列表类型的数据
range(n, m , k)左闭右开n初始值m-1结束值 k步长 递增或者递减的整数序列
默认生成从n ~ m-1并且间隔k的整数序列 对于这个序列我们可以通过list()转化为列表类型的数据
# 示例:
print(list(range(10))) # 输出结果: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(range(1, 10))) # 输出结果: [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list(range(2, 8, 2))) # 输出结果: [2, 4, 6]
print(list(range(101, 5, -5)))
# 输出结果: [101, 96, 91, 86, 81, 76, 71, 66, 61, 56, 51, 46, 41, 36, 31, 26, 21, 16, 11, 6]
print(list(range(5, 101, 5)))
# 输出结果: [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
******元组拆包*****
示例
tu = (111, 222)
a, b = tu
print(a, b) # 输出结果111 222
******函数*****
1. 常用的内置函数
type()查看数据的类型
id() 查看数据的内存地址
len()查看数据的长度
range() 生成数据
2. 函数的定义
def 函数名:
# 函数内部的功能代码
# 函数内部的功能代码
# 函数内部的功能代码
可以将单一的功能封装成一个函数在需要使用该功能的时候直接调用函数就可以了
函数的作用 封装代码
函数的意义提高代码的重用率
函数的命名规范可以由数字下划线组成不能使用数字开头不能使用python关键字不要和内置函数和模块第三方模块官方库重名
函数的命名风格推荐使用下划线命名法
示例
def func(n):
for i in range(n):
for j in range(i + 1):
print('* ', end='')
print()
func(5)
3. 函数的参数定义在函数后面的括号中
定义的参数叫形参调用函数的时候传入的参数叫实参
示例
def add_number(a, b):
print('a+b: ', a + b)
add_number(3, 5)
4. 函数的返回值return
# 注意如果接收到的数据为None 说明没有返回值
示例
def add_number(a, b):
return a + b
res = add_number(3, 5)
print(res)
"""

View File

@ -0,0 +1,125 @@
"""
=================================
Author: Flora Chen
Time: 2020/2/21 09:57
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
"""
1有1 2 3 4这四个数字设计程序计算能组成多少个互不相同且无重复数字的3位数分别是什么思路提示其实就是数学排列组合C4取3三层for循环嵌套可以实现
"""
count = 0
for i in range(1, 5):
for j in range(1, 5):
for m in range(1, 5):
if (i != j) and (i != m) and (j != m):
# i != j != m 这个是错误的!
count += 1
print('{}次组合:{} {} {}'.format(count, i, j, m))
"""
2小明有100块钱 需要买100本书钱要刚好花完a类数5元一本b类书3元一本c类书0.5元一本请计算小明有多少种购买的方式
"""
def buy_book(money, book_amount):
# 定义书本单价
a_book = 5.00
b_book = 3.00
c_book = 0.50
# 如果规定了每类书都要必须购买至少1本的话用range(1, book_amount+1)
for num1 in range(book_amount + 1):
for num2 in range(book_amount + 1):
for num3 in range(book_amount + 1):
if (money == (a_book * num1) + (b_book * num2) + (c_book * num3)) and (
book_amount == num1 + num2 + num3):
print('小明购买了{}本书其中A类书{}B类书{}本, C类书{}本,总花费{:.2f}元。'.format(book_amount, num1, num2, num3, money))
buy_book(100.00, 100)
# musen老师的代码
count = 0
for a in range(100 // 5 + 1):
for b in range(100 // 3 + 1):
if a * 5 + b * 3 + (100 - a - b) * 0.5 == 100:
count += 1
print('小明购买了100本书其中A类书{}B类书{}本, C类书{}总花费100元。'.format(a, b, (100 - a - b)))
print('一共有{}种买法'.format(count))
"""
4定义一个可以完成任意个数字相加的函数支持关键字传参和位置传参并返回相加结果
要求
调用函数传入1个数字返回值为这个数字 func(1) - ---> 返回1
调用函数传入2个数字返回值为2个数相加的结果 func(11, 22) - ---> 返回33
调用函数传入3个数字返回值为3个数相加的结果 func(11, 22, 33, ) - ---> 返回66
调用函数传入n个数字返回值为n个数相加的结果 func(1, 2, 3, 4, 5) - ---> 返回15
提示可以使用不定长参数来接收参数对参数进行遍历再相加
"""
# 方法一
def add_number(*args, **kwargs):
result = 0
for num in args:
result += num
# for num1 in kwargs.values:
# result += num1
for num1 in kwargs:
result += kwargs[num1]
return result
print(add_number(1))
print(add_number(1, 2, 3, 4, 5))
print(add_number(a=1, b=2, c=3, d=4, e=5))
print(add_number(11, b=33))
# 方法二 比较笨,忽略
# def get_numbers(*args, **kwargs):
# global li
# li = list(args)
# dic = dict(kwargs)
# for a in dic.values():
# li.append(a)
# return li
#
# def add_number():
# result = 0
# for b in li:
# result = result + b
# return result
#
# get_numbers(1)
# print(add_number())
#
# get_numbers(11, 22)
# print(add_number())
#
# get_numbers(11, b=33)
# print(add_number())
#
# get_numbers(a=1, b=2, c=3, d=4, e=5)
# print(add_number())
"""
4简单题
1什么是全局变量
全局变量直接定义在文件/模块中的变量在该文件的任何地方都可以访问
2什么是局部变量
局部变量定义在函数内部的变量只有在函数内部才可以访问
3函数内部如何声明全局变量
使用global声明例如 global a
4函数的形参有哪几种定义形式
形参的分类
必备参数必须参数定义了几个参数就要传递几个参数
默认参数缺省参数可传可不传不传的情况下使用默认值传了的情况下使用传的值
不定长参数位置可前可后但是一般放在后面
*args接收0个或多个位置参数
**kwargs接收0个或多个关键字参数
"""

View File

@ -0,0 +1,219 @@
"""
=================================
Author: Flora Chen
Time: 2020/2/22 19:27
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
"""
# 第一题:现有数据如下
users_title = ["name", "age", "gender"]
users_info = [['小明', 18, ''], ["小李", 19, ''], ["小美", 17, '']]
# 要求:请封装一个函数,上述两个列表作为参数传入,返回值为如下数据(提示:需要用到zip和for循环
users = [{'name': '小明', 'age': 18, 'gender': ''},
{'name': '小李', 'age': 19, 'gender': ''},
{'name': '小美', 'age': 17, 'gender': ''}]
"""
users_title = ["name", "age", "gender"]
users_info = [['小明', 18, ''], ["小李", 19, ''], ["小美", 17, '']]
def user_func(title, info):
users = []
for item in info:
users.append(dict(zip(title, item)))
return users
result = user_func(users_title, users_info)
# 按照老师题目中给出的格式输出
# new_result = 'users = [' + str(result[0]) + ',\n ' + str(result[1]) + ',\n ' + str(result[2]) + ']'
new_result = 'users = [{},\n{:>49},\n{:>49}]'.format(str(result[0]), str(result[1]), str(result[2]))
print(new_result)
# 弯弯绕绕的解题方法
# def user_func(title_len, *args):
# # 定义3个列表来接收新的列表
# users_title2 = []
# users_info2 = []
# users = []
#
# # 遍历传入的不定长参数,将值分情况保存到新列表中
# for item in args:
# if title_len <= 0:
# users_info2.append(item)
# else:
# users_title2.append(item)
# title_len -= 1
#
# # 对两个新列表进行打包,并转换成字典格式,然后保存在列表中
# for a in users_info2:
# users.append(dict(zip(users_title2, a)))
#
# # 返回新列表
# return users
#
# print(user_func(len(users_title), *users_title, *users_info))
"""
第二题请封装一个函数按要求实现数据的格式转换
# 传入参数: data = ["{'a':11,'b':2}", "[11,22,33,44]"]
# 返回结果res = [{'a': 11, 'b': 2}, [11, 22, 33, 44]]
# 通过代码将传入参数转换为返回结果所需数据,然后返回
"""
# 使用必备参数
def transform_data1(li):
res = []
for param in li:
res.append(eval(param))
return res
data = ["{'a':11,'b':2}", "[11,22,33,44]"]
print(transform_data1(data))
# 使用不定长参数
def transform_data2(*args):
res = []
for param in args:
res.append(eval(param))
return res
data = ["{'a':11,'b':2}", "[11,22,33,44]"]
print(transform_data2(*data))
"""
第三题当前有一个data.txt文件内容如下
数据aaa
数据bbb
数据ccc
数据ddd
# 要求:请将数据读取出来,保存为以下格式
{'data0': '数据aaa', 'data1': '数据bbb', 'data2': '数据ccc', 'data3': '数据ddd'}
# 提示思路:
#1、按行读取数据2、构造字典的键 3、打包为字典
# 注意点:读取出来的数据有换行符'\n',要想办法去掉
"""
# --------------------方法1--------------------
# 读取文件的内容
with open('data.txt', 'r', encoding='utf-8') as f:
data_value = []
data_key = []
datas = f.readlines()
for i in range(len(datas)):
data_key.append("data{}".format(i))
data_value.append(datas[i].replace('\n', ''))
data = dict(zip(data_key, data_value))
# --------------------方法2--------------------
# 读取数据,每一行作为一个元素放到列表中
with open('data.txt', 'r', encoding='utf-8') as f:
datas = f.readlines()
# 创建一个空字典
dic = {}
# 通过enumerate去获取列表中的数据和下标
for index, data in enumerate(datas):
key = 'data{}'.format(index)
value = data.replace('\n', '')
# 加入到字典中
dic[key] = value
# --------------------方法3--------------------
with open('data.txt', 'r', encoding='utf-8') as f:
data_value = []
data_key = ['data0', 'data1', 'data2', 'data3']
for i in f.readlines():
new_i = i.split('\n')
data_value.append(new_i[0])
data = dict(zip(data_key, data_value))
# 覆盖写入保存后的数据
with open('data.txt', 'w', encoding='utf-8') as f:
f.write(str(data))
"""
4继续扩展石头剪刀布的游戏想办法把每次游戏结果都写入到txt文件中保存文件中写入内容格式如下
"""
import random
# --------------------方法1--------------------
# 猜拳小游戏
def game():
print('---石头剪刀布游戏开始---')
print('请按照下面的提示出拳:')
li = ['石头', '剪刀', '']
game_results = []
while True:
print('石头【1】剪刀【2】布【3】/结束游戏【4】')
user_num = int(input('请输入你的选项:'))
r_num = random.randint(1, 3)
print(r_num)
if 1 <= user_num <= 3:
if r_num == user_num:
res1 = '您的出拳为:{} 电脑出拳:{},平局'.format(li[user_num - 1], li[r_num - 1])
game_results.append(res1)
print(res1)
elif (user_num - r_num) == -1 or (user_num - r_num) == 2:
res2 = '您的出拳为:{} 电脑出拳:{},您胜利了'.format(li[user_num - 1], li[r_num - 1])
game_results.append(res2)
print(res2)
else:
res3 = '您的出拳为:{} 电脑出拳:{},您输了'.format(li[user_num - 1], li[r_num - 1])
game_results.append(res3)
print(res3)
elif user_num == 4:
res4 = '游戏结束!'
game_results.append(res4)
print(res4)
break
else:
res5 = '您出拳有误,请按规矩出拳!!'
game_results.append(res5)
print(res5)
return game_results
# 将猜拳小游戏的结果覆盖写入文件中
def save_game():
# 追加写入游戏结果
with open('game.txt', 'w', encoding='utf-8') as f:
for game_result in game():
f.write(game_result + '\n')
# 调用函数
# save_game()
# --------------------方法2--------------------
with open('game.txt', 'w', encoding='utf-8') as f:
print('---石头剪刀布游戏开始---')
print('请按照下面的提示出拳:')
li = ['石头', '剪刀', '']
game_results = []
while True:
print('石头【1】剪刀【2】布【3】/结束游戏【4】')
user_num = int(input('请输入你的选项:'))
r_num = random.randint(1, 3)
print(r_num)
if 1 <= user_num <= 3:
if r_num == user_num:
f.write('您的出拳为:{} 电脑出拳:{},平局\n'.format(li[user_num - 1], li[r_num - 1]))
elif (user_num - r_num) == -1 or (user_num - r_num) == 2:
f.write('您的出拳为:{} 电脑出拳:{},您赢了\n'.format(li[user_num - 1], li[r_num - 1]))
else:
f.write('您的出拳为:{} 电脑出拳:{},您输了\n'.format(li[user_num - 1], li[r_num - 1]))
elif user_num == 4:
f.write('游戏结束!\n')
break
else:
f.write('您出拳有误,请按规矩出拳!\n')

View File

@ -0,0 +1,234 @@
"""
=================================
Author: Flora Chen
Time: 2020/2/25 19:27
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
"""
1实现一个文件复制器函数通过给函数传入一个路径复制该路径下面所有的文件(目录不用复制)到当前目录
提示os模块结合文件读写操作 即可实现
步骤提示获取指定路径下的所有文件信息判断是否是文件是文件则进行复制读取内容写入到新文件
"""
import os
# ------------------方法1--------------------
# 复制指定路径下的文件到当前文件所在的目录
def file_copy(path):
# 如果传入的是个目录就进行遍历文件复制
if os.path.isdir(path):
for file in os.listdir(path):
# 定位目标目录的文件
file_path = os.path.join(path, file)
# 如果是文件,则进行文件复制
if os.path.isfile(file_path):
# 读取文件的内容
with open(file_path, 'rb') as f:
content = f.read()
# 将上面读取到的内容写入到新文件中, 新文件跟当前文件同级并且命名带有cp
# with open(os.path.join(os.getcwd(), 'cp' + file), 'wb') as f:
with open('cp' + file, 'wb') as f:
f.write(content)
# 如果是文件的话,则直接复制
elif os.path.isfile(path):
# 读取文件的内容
with open(path, 'rb') as f:
content = f.read()
# 将上面读取到的内容写入到新文件中, 新文件跟当前文件同级并且命名带有cp
# with open(os.path.join(os.getcwd(), 'cp' + file), 'wb') as f:
with open('cp' + path, 'wb') as f:
f.write(content)
# 需要复制的文件所在的目录
target_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Pack')
file_copy(target_path)
# 复制当前文件所在目录下的所有文件到指定目录
# def files_copy(directory_name, path):
# # 判断当前工作路径下是否存在文件
# for file in os.listdir(path):
# # 在当前工作目录下面创建一个与当前文件同级的目录来保存复制的文件。不存在则创建。
# if directory_name not in os.listdir(path):
# os.mkdir(directory_name)
#
# # 如果是文件,则进行文件复制
# if os.path.isfile(file):
# # 在新目录下新建文件,读取当前工作目录下文件的内容
# with open(file, 'rb') as f:
# content = f.read()
#
# # 将上面读取到的内容写入到新文件中
# with open(os.path.join(directory_name, 'cp' + file), 'wb') as f:
# f.write(content)
# files_copy('TestDirectory', os.getcwd())
# ------------------方法2--------------------
# def copy_file(file):
# # 获取文件名以及后缀
# dest_file = 'cp' + os.path.basename(file)
#
# # 读取文件内容
# with open(file, 'rb') as f:
# content = f.read()
#
# # 在新文件中写入内容
# with open(dest_file, 'wb') as f:
# f.write(content)
#
#
# def is_file(path):
# # 获取当前目录下的所有文件
# for file in os.listdir(path):
# # 获取所有文件的绝对路径
# file_path = os.path.join(path, file)
#
# # 判断是否是文件是文件就调用copy_file
# if os.path.isfile(file_path):
# copy_file(file_path)
#
#
# is_file(target_path)
"""
case.txt文件里面中存储了很多用例数据: 如下每一行数据就是一条用例数据
# 文件中数据(可以先直接复制到文件中)
url:www.baidu.com,mobilephone:13760246701,pwd:123456
url:www.baidu.com,mobilephone:15678934551,pwd:234555
url:www.baidu.com,mobilephone:15678934551,pwd:234555
url:www.baidu.com,mobilephone:15678934551,pwd:234555
url:www.baidu.com,mobilephone:15678934551,pwd:234555
# 要求: 请把这些数据读取出来,转换为列表的格式:如下
[{'url': 'www.baidu.com', 'mobilephone': '13760246701', 'pwd': '123456'}, {'url': 'www.baidu.com', 'mobilephone': '15678934551', 'pwd': '234555'},{'url': 'www.baidu.com', 'mobilephone': '15678934551', 'pwd': '234555'},{'url': 'www.baidu.com', 'mobilephone': '15678934551', 'pwd': '234555'},
{'url': 'www.baidu.com', 'mobilephone': '15678934551', 'pwd': '234555'}]
# 提示:可以分析读取出来的每一行字符串中的内容,然后使用的字符串分割方法进行分割,想办法组装成字典。
# 注意点:数据中如果有换行符'\n',要想办法去掉
"""
# ------------------方法1--------------------
def read_data(file):
# 定义3个空列表来接收数据
key = []
value = []
case = []
# 读取文件中的内容
with open(file, 'r', encoding='utf-8') as f:
# 将读取的每一行内容使用‘,’分割
for i in f.readlines():
res = i.split(',')
# 遍历分割后的列表将元素的值分别追加到列表key和value中
for j in res:
res2 = j.split(':')
key.append(res2[0])
value.append(res2[1].replace('\n', ''))
# 将两个新列表打包成字典并追加到列表case中
case.append(dict(zip(key, value)))
return case
print(read_data('case.txt'))
# ------------------方法2--------------------
def analyse(file):
# 定义一个空列表来接收数据
case_list = []
# 打开文件
with open(file, 'r') as f:
# 按行读取文件中所有的内容
for line in f.readlines():
# 定义一个空字典来接收每一行的数据
case = {}
# 将每行内容使用逗号分隔
for sub in line.split(','):
# 再将列表中的每个元素用冒号分割
flied = sub.split(':')
# 如果有换行,则去除;并且# 给字典新增键值对
if flied[1].endswith('\n'):
case[flied[0]] = flied[1][:-1]
else:
case[flied[0]] = flied[1]
# 三目运算符 等同于上面的代码
# value[flied[0]] = flied[1][:-1]if flied[1].endswith('\n') else flied[1]
# 将得到的字典追加到列表中
case_list.append(case)
return case_list
print(analyse('case.txt'))
"""
3第三题练习模块导入的方式不用提交
Pass
"""
"""
4整理笔记
"""
"""
5编程逻辑扩展练习题(不用提交)
1有一个猴子第一天摘下若干个桃子当即吃了一半还不过瘾又多吃了一个第二天早上又将剩下的桃子吃掉一半又多吃了一个以后每天早上都吃了前一天剩下的一半 在加一个到第10天早上想再吃时见只剩下一个桃子了
请通过一段通过代码来计算 第一天摘了多少个桃子
2题目一球从100米高度自由落下每次落地后反跳回原高度的一半再落下求它在第10次落地时共经过多少米
"""
def monkey(days):
peach = 1
for day in range(1, days):
peach = (peach + 1) * 2
print('小猴子第1天总共摘了{}桃子'.format(peach))
return peach
print(monkey(10))
# def monkey(days):
# peach = 1534
# for day in range(1, days + 1):
# eat_peach = peach / 2 + 1
# peach = peach - eat_peach
# print('小猴子第{}天总共吃了{}桃子, 剩余{}'.format(day, eat_peach, peach))
# return peach
#
#
# print(monkey(10))
def ball(height, times):
count_height = 0
for count in range(1, times + 1):
if count == 1:
count_height = height
else:
count_height = count_height + height * 2
height = height / 2
print('{}次落地剩余{}米, 总共经过{}'.format(count, height, count_height))
return count_height
print(ball(100, 10))

View File

@ -0,0 +1,112 @@
"""
=================================
Author: Flora Chen
Time: 2020/2/26 19:17
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import random
"""
1优化之前作业的石头剪刀布游戏用户输入时如果输入非数字会引发异常请捕获这个异常提示用户重新输入
"""
def game():
with open('game.txt', 'w', encoding='utf-8') as f:
print('---石头剪刀布游戏开始---')
print('请按照下面的提示出拳:')
li = ['石头', '剪刀', '']
while True:
print('石头【1】剪刀【2】布【3】/结束游戏【4】')
try:
user_num = int(input('请输入你的选项:'))
except Exception as e:
f.write('捕获到的异常是:{}\n'.format(str(e)))
print('请重新输入你的选项!')
else:
r_num = random.randint(1, 3)
print(r_num)
if 1 <= user_num <= 3:
if r_num == user_num:
result = '您的出拳为:{} 电脑出拳:{},平局\n'.format(li[user_num - 1], li[r_num - 1])
elif (user_num - r_num) == -1 or (user_num - r_num) == 2:
result ='您的出拳为:{} 电脑出拳:{},您赢了\n'.format(li[user_num - 1], li[r_num - 1])
else:
result ='您的出拳为:{} 电脑出拳:{},您输了\n'.format(li[user_num - 1], li[r_num - 1])
f.write(result)
elif user_num == 4:
print('游戏结束!\n')
break
else:
print('您出拳有误,请按规矩出拳!\n')
game()
"""
2写出异常处理语句中try作用是什么except,else,finally下面的代码分别在什么时候会执行简答题
答案
try是用来捕获异常的
except的代码在发生异常的时候会执行
else的代码在没有发生异常的时候会执行
finally的代码不管是否捕获到异常都会执行
"""
"""
3用户输入一个数值打印1到这个数值之间所有的偶数及其偶数个数及其它们的平均值如果输入非数值请让用户重新输入
"""
# 输入0 1 负数会报错 ZeroDivisionError: division by zero
# result = sum(even_numbers) / len(even_numbers)
def numbers():
while True:
# 定义一个空列表来接收偶数
even_numbers = []
# 捕获异常
try:
number = int(input('请输入一个数值:'))
# 如果捕获到了异常就打印出捕获的异常
except Exception as e:
print('捕获到了异常:{}'.format(e))
print('您的输入有误,请重新输入!')
# 如果没有捕获到异常就去计算1到该数值之间的偶数
else:
for num in range(1, number + 1):
if int(num % 2) == 0:
even_numbers.append(num)
print('1到该数值之间的偶数有{}'.format(num))
result = sum(even_numbers) / len(even_numbers)
print('1到该数值之间的偶数总共有{}个, 它们的平均值是{}'.format(len(even_numbers), result))
break
numbers()
"""
4整理笔记
"""
"""
5逻辑扩展题不用提交
1小明买了一对刚出生的兔子兔子从出生后第3个月起每个月都生一对兔子生的这对小兔子长到第三个月也开始生兔子每个月生一对兔子
假如兔子都不死问10个月后小明的兔子为多少对思路提示重点在分析出兔子增长的规律分析出规则之后通过for循环即可实现
"""
# month表示第几个月后兔子达到的数量 interval表示间隔几个月兔子会再生兔子
def cal_rabbit(month, interval):
first_rabbit = 1
rabbits = []
for i in range(1, month + 1):
if 1 <= i < 3:
rabbits.append(first_rabbit)
print('{}月兔子的数量为{}'.format(i, rabbits[i-1]))
else:
rabbits.append(rabbits[i - (interval+1)] + rabbits[i - interval])
print('{}月兔子的数量为{}'.format(i, rabbits[i-1]))
print('10个月后小明的兔子为{}'.format(rabbits[-1]))
cal_rabbit(10, 2)

View File

@ -0,0 +1,111 @@
"""
=================================
Author: Flora Chen
Time: 2020/2/29 9:22
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
"""
1类属性怎么定义 实例属性怎么定义
答案
类属性是定义在类里面的属性属性名=属性值
实例属性是通过实例对象来定义的属性对象.属性名=属性值
"""
class ClassDefine:
# 这是类属性
attribute_01 = '类属性1'
attribute_02 = '类属性2'
# 实例属性
def __init__(self, attr_03, attr_04):
self.attr_03 = attr_03
self.attr_04 = attr_04
"""
2实例方法中的self代表什么简答
答案
self代表实例化对象本身
self代表实例对象
实例对象生成以后要实现功能它必须要去调用类里的属性和方法所以类里面的self就是哪个实例对象在调用类里的代码self就代表谁定义类时代码要引用实例属性和实例对象的也都需要self.来调用
"""
"""
3类中__init__方法在什么时候会调用的简答
答案
类中__init__方法在实例化对象的时候会调用
__init__()方法可以创建实例属性__init__()方法就是初始化方法
当你创建一个实例对象的时候这个函数就会被调用
在执行 实例对象 = ()的语句时就会自动调用__init__(self)函数
"""
"""
4定义一个登录的测试用例类LoginTestCase
登录url地址为"http://www.xxxx.com/login"
请求方法为"post"
请自行分辨下列属性应该定义为类属性还是实例属性
- 属性
用例编号
url地址
请求参数
请求方法
预期结果
实际结果
"""
class LoginTestCase:
# 类属性
url = "http://www.xxxx.com/login"
method = "post"
# 实例属性
def __init__(self, case_num, para, except_result, actual_result):
self.case_num = case_num # 用例编号
self.para = para # 请求参数
self.except_result = except_result # 预期结果
self.actual_result = actual_result # 实际结果
"""
5封装一个学生类(自行分辨定义为类属性还是实例属性方法定义为实例方法)
- 属性身份(学生)姓名年龄性别英语成绩数学成绩语文成绩
- 方法一计算总分方法二计算三科平均分方法三打印学生的个人信息我的名字叫XXX年龄xxx, 性别xxx
"""
class Student:
identity = '学生'
def __init__(self, name, age, gender, english_score, math_score, language_score):
self.name = name
self.age = age
self.gender = gender
self.english_score = english_score
self.math_score = math_score
self.language_score = language_score
def sum_score(self):
score = self.english_score + self.math_score + self.language_score
return score
def avg_score(self):
avg = self.sum_score() / 3
return avg
def student_info(self):
print('我的名字叫{},年龄:{}, 性别:{}'.format(self.name, self.age, self.gender))
student = Student('flora', 23, 'female', 89, 90, 100)
print(student.sum_score())
print(student.avg_score())
student.student_info()

View File

@ -0,0 +1,96 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/3 19:48
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
"""
1上课的手机类继承代码自己敲一遍进行提交
"""
class PhoneV1(object):
def call(self):
print('打电话的功能')
class PhoneV2(PhoneV1):
def listen_music(self):
print('听音乐的功能')
def send_message(self):
print('发短信的功能')
class PhoneV3(PhoneV2):
def we_chat(self):
print('聊微信的功能')
def play_game(self):
print('玩游戏的功能')
# v1对应的类
print('------v1对应的类------')
v1 = PhoneV1()
v1.call()
# 父类不能调用子类的方法
# v1.listen_music() # 报错AttributeError: 'PhoneV1' object has no attribute 'listen_music'
# v2对应的类
print('------v2对应的类------')
v2 = PhoneV2()
# 子类可以调用父类的方法
v2.call()
v2.listen_music()
v2.send_message()
# v3对应的类
print('------v3对应的类------')
v3 = PhoneV3()
v3.call()
v3.listen_music()
v3.send_message()
v3.we_chat()
v3.play_game()
"""
2有一组数据如下格式
{'case_id': 1, 'method': 'post', 'url': '/member/login', 'data': '123', 'actual': '不通过','excepted': '通过'},
定义一个如下的类请通过setattr将上面字典中的键值对分别设置为类的属性和属性值键作为属性名对应的值作为属性值
class CaseData:
pass
"""
# 定义一个类
class CaseData:
pass
# 定义一组数据
data = {'case_id': 1, 'method': 'post', 'url': '/member/login', 'data': '123', 'actual': '不通过','excepted': '通过'}
# 将上面字典中的key设置为属性名value设置为属性值
for key, value in data.items():
# 动态设置类的属性
setattr(CaseData, key, value)
# 实例化对象
case = CaseData()
# 通过实例化对象访问类中的类属性
print('通过实例化对象访问类中的类属性:', case.case_id)
print('通过实例化对象访问类中的类属性:', case.method)
print('通过实例化对象访问类中的类属性:', case.url)
print('通过实例化对象访问类中的类属性:', case.data)
print('通过实例化对象访问类中的类属性:', case.actual)
print('通过实例化对象访问类中的类属性:', case.excepted)
# 通过类访问类中的类属性
print('通过类访问类中的类属性:', CaseData.case_id)
print('通过类访问类中的类属性:', CaseData.method)
print('通过类访问类中的类属性:', CaseData.url)
print('通过类访问类中的类属性:', CaseData.data)
print('通过类访问类中的类属性:', CaseData.actual)
print('通过类访问类中的类属性:', CaseData.excepted)
"""
3python基础语法到此就差不多结束了本次不布置过多的作业将基础阶段的基本语法内容先消化一下后面就是类的各种应用了
"""

View File

@ -0,0 +1,68 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/6 8:59
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
users = [{'user': 'python26', 'password': '123456'}]
def register(username, password1, password2):
"""
:param username:
:param password1:
:param password2:
:return:
"""
# 判断是否有参数为空
if not all([username, password1, password2]):
return {"code": 0, "msg": "所有参数不能为空"}
# 注册功能
for user in users: # 遍历出所有账号,判断账号是否存在
if username == user['user']:
# 账号存在
return {"code": 0, "msg": "该账户已存在"}
else:
if password1 != password2:
# 两次密码不一致
return {"code": 0, "msg": "两次密码不一致"}
else:
# 账号不存在 密码不重复,判断账号密码长度是否在 6-18位之间
if 6 <= len(username) >= 6 and 6 <= len(password1) <= 18:
# 注册账号
users.append({'user': username, 'password': password2})
return {"code": 1, "msg": "注册成功"}
else:
# 账号密码长度不对,注册失败
return {"code": 0, "msg": "账号和密码必须在6-18位之间"}
if __name__ == "__main__":
res = register('python14', '123456', '123456')
print(res)
"""
函数入参
注意参数传字符串类型不需要考虑其他类型
参数1账号
参数2密码1
参数2密码2
函数内部处理的逻辑
判断是否有参数为空
判断账号密码是否在6-18位之间
判断账号是否被注册过
判断两个密码是否一致
上面添加都校验通过才能注册成功其他情况都注册失败
各种情况的返回结果如下
注册成功 返回结果{"code": 1, "msg": "注册成功"}
有参数为空 返回结果 {"code": 0, "msg": "所有参数不能为空"}
两次密码不一致 返回结果{"code": 0, "msg": "两次密码不一致"}
账户已存在 返回结果{"code": 0, "msg": "该账户已存在"}
密码不在6-18位之间 返回结果{"code": 0, "msg": "账号和密码必须在6-18位之间"}
账号不在6-18位之间 返回结果{"code": 0, "msg": "账号和密码必须在6-18位之间"}
"""

View File

@ -0,0 +1,65 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/6 9:33
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
import os
from BeautifulReport import BeautifulReport
from HTMLTestRunner import HTMLTestRunner
# 要执行的测试用例的位置
path =os.path.dirname(os.path.abspath(__file__))
"""
第一步创建测试套件
"""
# suite = unittest.TestSuite()
"""
第二步加载测试用例到测试套件
# 第三种:通过路径去加载所有的测试用例 (推荐这一种)
# 注意默认去找指定路径中test开头的模块中的测试用例
"""
# loader = unittest.TestLoader()
# suite.addTest(loader.discover(path))
"""
综合第一步和第二步创建套件并加载用例
"""
suite= unittest.defaultTestLoader.discover(path)
"""
第三步1执行测试套件中的用例没有漂亮的HTML报告只在控制台简单显示测试结果
"""
# runner = unittest.TextTestRunner()
# runner.run(suite)
# 测试报告存放的路径
report_path = os.path.join(path, 'testReport')
"""
第三步2执行测试套件中的用例 使用BeautifulReport生成HTML测试报告
2个参数报告描述用例名称报告文件名
report_dir用来指定报告的存放位置
"""
b_report = BeautifulReport(suite)
b_report.report('Register Function Report by flora',
'register_beautiful_report.html',
report_dir=report_path
)
"""
第三步3执行测试套件中的用例 使用HTMLTestRunner生成HTML测试报告
stream表示报告存放的位置文件名以及写入的模式
title表示报告的标题
tester表示测试人员
description表示对测试报告的描述
"""
# runner = HTMLTestRunner(stream=open(os.path.join(report_path, 'register_tr_report.html'), 'wb'),
# title='Register Function Report',
# tester='flora.chen',
# description='Version 1.0')
# runner.run(suite)

View File

@ -0,0 +1,97 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/6 9:01
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
from python27Class.homeWork.unitTest.homeWork03052020.registerPage import register
class RegisterTestCase(unittest.TestCase):
# 注册成功
def test_register_pass(self):
# 第一步:准备用例数据
# 第二步:获取实际结果(调用功能函数,传入参数,获取实际结果)
# 第三步:断言(比对预期结果和实际结果)
# 参数准备
user_info = {'username': 'floraachy', 'password1': '12345678Az', 'password2': '12345678Az'}
# 预期结果准备
expect_result = {"code": 1, "msg": "注册成功"}
# 获取实际结果
actual_result = register(**user_info)
# 断言
self.assertEqual(expect_result, actual_result)
# 注册账号已存在
def test_register_user_exist(self):
user_info = {'username': 'python26', 'password1': '123456', 'password2': '123456'}
expect_result = {"code": 0, "msg": "该账户已存在"}
actual_result = register(**user_info)
self.assertEqual(expect_result, actual_result)
# 用户名或者密码1或者密码2为空的情况下注册
def test_register_user_null(self):
user_info = {'username': None, 'password1': '12345678Az', 'password2': '12345678Az'}
# 以下方式传值会报错,缺少参数
# user_info = {'password1': '12345678Az', 'password2': '12345678Az'}
expect_result = {"code": 0, "msg": "所有参数不能为空"}
actual_result = register(**user_info)
self.assertEqual(expect_result, actual_result)
def test_register_pwd1_null(self):
user_info = {'username': 'flora.chen', 'password1': None, 'password2': '12345678Az'}
expect_result = {"code": 0, "msg": "所有参数不能为空"}
actual_result = register(**user_info)
self.assertEqual(expect_result, actual_result)
def test_register_pwd2_null(self):
user_info = {'username': 'flora.chen', 'password1': '12345678Az', 'password2': None}
expect_result = {"code": 0, "msg": "所有参数不能为空"}
actual_result = register(**user_info)
self.assertEqual(expect_result, actual_result)
# 两次输入的密码不一致的情况下注册
def test_register_pwd1_pwd2_unequal(self):
user_info = {'username': 'flora.chen', 'password1': '123456', 'password2': '1234567890'}
expect_result = {"code": 0, "msg": "两次密码不一致"}
actual_result = register(**user_info)
self.assertEqual(expect_result, actual_result)
# 用户名长度小于6或者大于18的情况下注册
def test_register_user_length_5(self):
user_info = {'username': 'chen', 'password1': '1234567', 'password2': '1234567'}
expect_result = {"code": 0, "msg": "账号和密码必须在6-18位之间"}
actual_result = register(**user_info)
self.assertEqual(expect_result, actual_result)
def test_register_user_length_19(self):
user_info = {'username': 'username.username.c', 'password1': '123456789', 'password2': '12345678'}
expect_result = {"code": 0, "msg": "账号和密码必须在6-18位之间"}
actual_result = register(**user_info)
self.assertEqual(expect_result, actual_result)
# 密码长度小于6或者大于18的情况下注册
def test_register_pwd_length_5(self):
user_info = {'username': 'flora.chen', 'password1': '12345', 'password2': '12345'}
expect_result = {"code": 0, "msg": "账号和密码必须在6-18位之间"}
actual_result = register(**user_info)
self.assertEqual(expect_result, actual_result)
def test_register_pwd_length_19(self):
user_info = {'username': 'flora.chen', 'password1': '1234567890123456789', 'password2': '1234567890123456789'}
expect_result = {"code": 0, "msg": "账号和密码必须在6-18位之间"}
actual_result = register(**user_info)
self.assertEqual(expect_result, actual_result)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,319 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 10:52
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
# -*- coding: utf-8 -*-
# This file is a part of DDT (https://github.com/datadriventests/ddt)
# Copyright 2012-2015 Carles Barrobés and DDT contributors
# For the exact contribution history, see the git revision log.
# DDT is licensed under the MIT License, included in
# https://github.com/datadriventests/ddt/blob/master/LICENSE.md
import inspect
import json
import os
import re
import codecs
from functools import wraps
try:
import yaml
except ImportError: # pragma: no cover
_have_yaml = False
else:
_have_yaml = True
__version__ = '1.2.2'
# These attributes will not conflict with any real python attribute
# They are added to the decorated test method and processed later
# by the `ddt` class decorator.
DATA_ATTR = '%values' # store the data the test must run with
FILE_ATTR = '%file_path' # store the path to JSON file
UNPACK_ATTR = '%unpack' # remember that we have to unpack values
index_len = 5 # default max length of case index
try:
trivial_types = (type(None), bool, int, float, basestring)
except NameError:
trivial_types = (type(None), bool, int, float, str)
def is_trivial(value):
if isinstance(value, trivial_types):
return True
elif isinstance(value, (list, tuple)):
return all(map(is_trivial, value))
return False
def unpack(func):
"""
Method decorator to add unpack feature.
"""
setattr(func, UNPACK_ATTR, True)
return func
def data(*values):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
"""
global index_len
index_len = len(str(len(values)))
return idata(values)
def idata(iterable):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
"""
def wrapper(func):
setattr(func, DATA_ATTR, iterable)
return func
return wrapper
def file_data(value):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
``value`` should be a path relative to the directory of the file
containing the decorated ``unittest.TestCase``. The file
should contain JSON encoded data, that can either be a list or a
dict.
In case of a list, each value in the list will correspond to one
test case, and the value will be concatenated to the test method
name.
In case of a dict, keys will be used as suffixes to the name of the
test case, and values will be fed as test data.
"""
def wrapper(func):
setattr(func, FILE_ATTR, value)
return func
return wrapper
def mk_test_name(name, value, index=0):
"""
Generate a new name for a test case.
It will take the original test name and append an ordinal index and a
string representation of the value, and convert the result into a valid
python identifier by replacing extraneous characters with ``_``.
We avoid doing str(value) if dealing with non-trivial values.
The problem is possible different names with different runs, e.g.
different order of dictionary keys (see PYTHONHASHSEED) or dealing
with mock objects.
Trivial scalar values are passed as is.
A "trivial" value is a plain scalar, or a tuple or list consisting
only of trivial values.
"""
# Add zeros before index to keep order
index = "{0:0{1}}".format(index + 1, index_len)
if not is_trivial(value):
return "{0}_{1}".format(name, index)
try:
value = str(value)
except UnicodeEncodeError:
# fallback for python2
value = value.encode('ascii', 'backslashreplace')
test_name = "{0}_{1}_{2}".format(name, index, value)
return re.sub(r'\W|^(?=\d)', '_', test_name)
def feed_data(func, new_name, test_data_docstring, *args, **kwargs):
"""
This internal method decorator feeds the test data item to the test.
"""
@wraps(func)
def wrapper(self):
return func(self, *args, **kwargs)
wrapper.__name__ = new_name
wrapper.__wrapped__ = func
# set docstring if exists
if test_data_docstring is not None:
wrapper.__doc__ = test_data_docstring
else:
# Try to call format on the docstring
if func.__doc__:
try:
wrapper.__doc__ = func.__doc__.format(*args, **kwargs)
except (IndexError, KeyError):
# Maybe the user has added some of the formating strings
# unintentionally in the docstring. Do not raise an exception
# as it could be that user is not aware of the
# formating feature.
pass
return wrapper
def add_test(cls, test_name, test_docstring, func, *args, **kwargs):
"""
Add a test case to this class.
The test will be based on an existing function but will give it a new
name.
"""
setattr(cls, test_name, feed_data(func, test_name, test_docstring,
*args, **kwargs))
def process_file_data(cls, name, func, file_attr):
"""
Process the parameter in the `file_data` decorator.
"""
cls_path = os.path.abspath(inspect.getsourcefile(cls))
data_file_path = os.path.join(os.path.dirname(cls_path), file_attr)
def create_error_func(message): # pylint: disable-msg=W0613
def func(*args):
raise ValueError(message % file_attr)
return func
# If file does not exist, provide an error function instead
if not os.path.exists(data_file_path):
test_name = mk_test_name(name, "error")
test_docstring = """Error!"""
add_test(cls, test_name, test_docstring,
create_error_func("%s does not exist"), None)
return
_is_yaml_file = data_file_path.endswith((".yml", ".yaml"))
# Don't have YAML but want to use YAML file.
if _is_yaml_file and not _have_yaml:
test_name = mk_test_name(name, "error")
test_docstring = """Error!"""
add_test(
cls,
test_name,
test_docstring,
create_error_func("%s is a YAML file, please install PyYAML"),
None
)
return
with codecs.open(data_file_path, 'r', 'utf-8') as f:
# Load the data from YAML or JSON
if _is_yaml_file:
data = yaml.safe_load(f)
else:
data = json.load(f)
_add_tests_from_data(cls, name, func, data)
def _add_tests_from_data(cls, name, func, data):
"""
Add tests from data loaded from the data file into the class
"""
for i, elem in enumerate(data):
if isinstance(data, dict):
key, value = elem, data[elem]
test_name = mk_test_name(name, key, i)
elif isinstance(data, list):
value = elem
test_name = mk_test_name(name, value, i)
if isinstance(value, dict):
add_test(cls, test_name, test_name, func, **value)
else:
add_test(cls, test_name, test_name, func, value)
def _is_primitive(obj):
"""Finds out if the obj is a "primitive". It is somewhat hacky but it works.
"""
return not hasattr(obj, '__dict__')
def _get_test_data_docstring(func, value):
"""Returns a docstring based on the following resolution strategy:
1. Passed value is not a "primitive" and has a docstring, then use it.
2. In all other cases return None, i.e the test name is used.
"""
if not _is_primitive(value) and value.__doc__:
return value.__doc__
else:
return None
def ddt(cls):
"""
Class decorator for subclasses of ``unittest.TestCase``.
Apply this decorator to the test case class, and then
decorate test methods with ``@data``.
For each method decorated with ``@data``, this will effectively create as
many methods as data items are passed as parameters to ``@data``.
The names of the test methods follow the pattern
``original_test_name_{ordinal}_{data}``. ``ordinal`` is the position of the
data argument, starting with 1.
For data we use a string representation of the data value converted into a
valid python identifier. If ``data.__name__`` exists, we use that instead.
For each method decorated with ``@file_data('test_data.json')``, the
decorator will try to load the test_data.json file located relative
to the python file containing the method that is decorated. It will,
for each ``test_name`` key create as many methods in the list of values
from the ``data`` key.
"""
for name, func in list(cls.__dict__.items()):
if hasattr(func, DATA_ATTR):
for i, v in enumerate(getattr(func, DATA_ATTR)):
test_name = mk_test_name(name, getattr(v, "__name__", v), i)
# 将用例描述信息改为用例数据的title字段
# 原代码test_data_docstring = _get_test_data_docstring(func, v)
test_data_docstring = v['title']
if hasattr(func, UNPACK_ATTR):
if isinstance(v, tuple) or isinstance(v, list):
add_test(
cls,
test_name,
test_data_docstring,
func,
*v
)
else:
# unpack dictionary
add_test(
cls,
test_name,
test_data_docstring,
func,
**v
)
else:
add_test(cls, test_name, test_data_docstring, func, v)
delattr(cls, name)
elif hasattr(func, FILE_ATTR):
file_attr = getattr(func, FILE_ATTR)
process_file_data(cls, name, func, file_attr)
delattr(cls, name)
return cls

View File

@ -0,0 +1,21 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/5 20:42
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
def login_check(username=None, passwd=None):
"""
登录校验的函数
:param username:
:param passwd:
:return: dict type
"""
if username != None and passwd != None:
if username == 'flora' and passwd == '1234567Az':
return {'code': 0, 'msg': '登录成功'}
else:
return {'code': 1, 'msg': '账号或者密码不正确'}
else:
return {'code': 1, 'msg': '账号和密码不能为空'}

View File

@ -0,0 +1,59 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 18:58
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import openpyxl
import os
# 从excel表格中读取数据
def login_data():
# 获取excel的路径
data_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'casesData.xlsx')
# 将指定的excel文件加载为一个workbook对象
work_book = openpyxl.load_workbook(data_path)
# 选中工作簿中的表单对象
sheet_name = work_book['casesData']
# 按行读取表格中所有数据
excel_data = list(sheet_name.rows)
# 定义两个空列表来接收数据
data_key = []
data_value = []
# 定义一个列表来接收用例数据
cases_data = []
is_first_line = True
for line in excel_data:
# 如果是第一行数据就将每个单元格数据追加到列表data_key中
if is_first_line:
is_first_line = False
for column in line:
data_key.append(column.value)
continue
# 将剩余行数据中每个单元格数据追加到列表data_value中
i = 0
for column in line:
i += 1
# 如果是第2列则先获取单元格中的有效表达式字典再追加到data_value中
if i == 2:
data_value.append(eval(column.value))
continue
# 其他列直接追加到列表data_value中
data_value.append(column.value)
# 将两个列表打包成字典追加到保存用例数据的列表中
cases_data.append(dict(zip(data_key, data_value)))
# 清空列表data_value中的值否则每次打包的数据都会是相同的数据
data_value.clear()
return cases_data

View File

@ -0,0 +1,87 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/5 21:11
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
import os
"""
第一步创建测试套件
"""
# suite = unittest.TestSuite()
"""
第二步加载测试用例到测试套件
"""
# 第一种:通过测试用例类去加载
# from python27Class.homeWork.unitTest.homeWork03072020.testLogin import LoginTestCase
# loader = unittest.TestLoader()
# suite.addTest(loader.loadTestsFromTestCase(LoginTestCase))
# 第二种:通过测试用例模块去加载
# 用例加载器对象
# from python27Class.homeWork.unitTest.homeWork03072020 import testLogin
# loader=unittest.TestLoader()
# suite.addTest(loader.loadTestsFromModule(testLogin))
# 第三种:通过路径去加载所有的测试用例 (推荐这一种)
# 注意默认去找指定路径中test开头的模块中的测试用例
# path = os.path.dirname(os.path.abspath(__file__))
# loader = unittest.TestLoader()
# suite.addTest(loader.discover(path))
# 第四种:一条条去加载
# from python27Class.homeWork.unitTest.homeWork03072020.testLogin import LoginTestCase
# case1 = LoginTestCase('test_login')
# suite.addTest(case1)
# # 报错: AttributeError: 'LoginTestCase' object has no attribute 'test_login'
"""
综合第一步和第二步创建套件并加载用例
"""
path = os.path.dirname(os.path.abspath(__file__))
suite = unittest.defaultTestLoader.discover(path)
"""
第三步(1)执行测试套件中的用例, 控制台生成报告
"""
# 仅执行,未生成测试报告
# 创建测试运行程序
# runner = unittest.TextTestRunner()
# runner.run(suite)
# ----------------------------------------------
# 执行并生成测试报告
"""
第三步(2)使用BeautifulReport来执行测试套件中的用例并生成报告
# 2个参数报告描述用例名称报告文件名
report_dir用来指定报告的存放位置
"""
# from BeautifulReport import BeautifulReport
# beauty_report = BeautifulReport(suite)
# report_path = os.path.join(path, 'testReport')
# beauty_report.report('Login Function Test Report by flora',
# 'login_test_report_Beauty.html',
# report_dir=report_path)
# ----------------------------------------------
"""
第三步(3)使用HTMLTestRunner来生成测试报告
stream表示报告存放的位置以及写入的模式
title表示报告的标题
tester表示测试人员
description表示对测试报告的描述
"""
from HTMLTestRunner import HTMLTestRunner
report_path = os.path.join(path, 'testReport')
runner = HTMLTestRunner(stream=open(os.path.join(report_path, 'login_test_report_HTML.html'), 'wb'),
title='Login Function Test Report',
tester='flora.chen',
description='Version 1.0')
runner.run(suite)

View File

@ -0,0 +1,54 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/5 20:23
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
from python27Class.homeWork.unitTest.homeWork03072020.demo1.login import login_check
from python27Class.homeWork.unitTest.homeWork03072020.demo1.readExcel import login_data
from python27Class.homeWork.unitTest.homeWork03072020.demo1.ddtNew import ddt, data
"""
# 定义测试用例类必须继承unittest.TestCase
# 定义测试用例在测试用例类中每一个以test开头的方法就是一条用例
# unittest中测试用例执行的顺序是根据方法名按ASCII码进行排序的
# unittest中会自动根据用例方法执行的时候是否出现断言异常来评判用例执行是否通过
"""
@ddt
class LoginTestCase(unittest.TestCase):
# 第一步:准备用例数据
# 第二步:获取实际结果(调用功能函数,传入参数,获取实际结果)
# 第三步:断言(比对预期结果和实际结果)
# 方式一:直接定义列表作为测试数据
# cases_data = [
# {'title': '登录成功', 'expect_result': {'code': 0, 'msg': '登录成功'}, 'data': {'username': 'flora', 'passwd': '1234567Az'}},
# {'title': '账号不正确', 'expect_result': {"code": 1, "msg": "账号或者密码不正确"}, 'data': {'username': 'flora.chen', 'passwd': '1234567Az'}},
# {'title': '密码不正确', 'expect_result': {"code": 1, "msg": "账号或者密码不正确"}, 'data': {'username': 'flora', 'passwd': '1234567'}},
# {'title': '账号为空', 'expect_result': {"code": 1, "msg": "账号和密码不能为空"},'data': {'passwd': '1234567Az'}},
# {'title': '密码为空', 'expect_result': {"code": 1, "msg": "账号和密码不能为空"},'data': {'username': 'flora'}},
# ]
# 这里使用方式二从excel中读取用例数据
@data(*login_data())
def test_login_case(self, case_data):
# 预期结果准备
expect_result = case_data['expect_result']
# 获取实际结果
actual_result = login_check(case_data['username'], case_data['passwd'])
# 断言
self.assertEqual(expect_result, actual_result)
if __name__ == '__main__':
login_test = LoginTestCase()
login_test.test_login_case(*login_test.cases_data)

View File

@ -0,0 +1,319 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 10:52
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
# -*- coding: utf-8 -*-
# This file is a part of DDT (https://github.com/datadriventests/ddt)
# Copyright 2012-2015 Carles Barrobés and DDT contributors
# For the exact contribution history, see the git revision log.
# DDT is licensed under the MIT License, included in
# https://github.com/datadriventests/ddt/blob/master/LICENSE.md
import inspect
import json
import os
import re
import codecs
from functools import wraps
try:
import yaml
except ImportError: # pragma: no cover
_have_yaml = False
else:
_have_yaml = True
__version__ = '1.2.2'
# These attributes will not conflict with any real python attribute
# They are added to the decorated test method and processed later
# by the `ddt` class decorator.
DATA_ATTR = '%values' # store the data the test must run with
FILE_ATTR = '%file_path' # store the path to JSON file
UNPACK_ATTR = '%unpack' # remember that we have to unpack values
index_len = 5 # default max length of case index
try:
trivial_types = (type(None), bool, int, float, basestring)
except NameError:
trivial_types = (type(None), bool, int, float, str)
def is_trivial(value):
if isinstance(value, trivial_types):
return True
elif isinstance(value, (list, tuple)):
return all(map(is_trivial, value))
return False
def unpack(func):
"""
Method decorator to add unpack feature.
"""
setattr(func, UNPACK_ATTR, True)
return func
def data(*values):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
"""
global index_len
index_len = len(str(len(values)))
return idata(values)
def idata(iterable):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
"""
def wrapper(func):
setattr(func, DATA_ATTR, iterable)
return func
return wrapper
def file_data(value):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
``value`` should be a path relative to the directory of the file
containing the decorated ``unittest.TestCase``. The file
should contain JSON encoded data, that can either be a list or a
dict.
In case of a list, each value in the list will correspond to one
test case, and the value will be concatenated to the test method
name.
In case of a dict, keys will be used as suffixes to the name of the
test case, and values will be fed as test data.
"""
def wrapper(func):
setattr(func, FILE_ATTR, value)
return func
return wrapper
def mk_test_name(name, value, index=0):
"""
Generate a new name for a test case.
It will take the original test name and append an ordinal index and a
string representation of the value, and convert the result into a valid
python identifier by replacing extraneous characters with ``_``.
We avoid doing str(value) if dealing with non-trivial values.
The problem is possible different names with different runs, e.g.
different order of dictionary keys (see PYTHONHASHSEED) or dealing
with mock objects.
Trivial scalar values are passed as is.
A "trivial" value is a plain scalar, or a tuple or list consisting
only of trivial values.
"""
# Add zeros before index to keep order
index = "{0:0{1}}".format(index + 1, index_len)
if not is_trivial(value):
return "{0}_{1}".format(name, index)
try:
value = str(value)
except UnicodeEncodeError:
# fallback for python2
value = value.encode('ascii', 'backslashreplace')
test_name = "{0}_{1}_{2}".format(name, index, value)
return re.sub(r'\W|^(?=\d)', '_', test_name)
def feed_data(func, new_name, test_data_docstring, *args, **kwargs):
"""
This internal method decorator feeds the test data item to the test.
"""
@wraps(func)
def wrapper(self):
return func(self, *args, **kwargs)
wrapper.__name__ = new_name
wrapper.__wrapped__ = func
# set docstring if exists
if test_data_docstring is not None:
wrapper.__doc__ = test_data_docstring
else:
# Try to call format on the docstring
if func.__doc__:
try:
wrapper.__doc__ = func.__doc__.format(*args, **kwargs)
except (IndexError, KeyError):
# Maybe the user has added some of the formating strings
# unintentionally in the docstring. Do not raise an exception
# as it could be that user is not aware of the
# formating feature.
pass
return wrapper
def add_test(cls, test_name, test_docstring, func, *args, **kwargs):
"""
Add a test case to this class.
The test will be based on an existing function but will give it a new
name.
"""
setattr(cls, test_name, feed_data(func, test_name, test_docstring,
*args, **kwargs))
def process_file_data(cls, name, func, file_attr):
"""
Process the parameter in the `file_data` decorator.
"""
cls_path = os.path.abspath(inspect.getsourcefile(cls))
data_file_path = os.path.join(os.path.dirname(cls_path), file_attr)
def create_error_func(message): # pylint: disable-msg=W0613
def func(*args):
raise ValueError(message % file_attr)
return func
# If file does not exist, provide an error function instead
if not os.path.exists(data_file_path):
test_name = mk_test_name(name, "error")
test_docstring = """Error!"""
add_test(cls, test_name, test_docstring,
create_error_func("%s does not exist"), None)
return
_is_yaml_file = data_file_path.endswith((".yml", ".yaml"))
# Don't have YAML but want to use YAML file.
if _is_yaml_file and not _have_yaml:
test_name = mk_test_name(name, "error")
test_docstring = """Error!"""
add_test(
cls,
test_name,
test_docstring,
create_error_func("%s is a YAML file, please install PyYAML"),
None
)
return
with codecs.open(data_file_path, 'r', 'utf-8') as f:
# Load the data from YAML or JSON
if _is_yaml_file:
data = yaml.safe_load(f)
else:
data = json.load(f)
_add_tests_from_data(cls, name, func, data)
def _add_tests_from_data(cls, name, func, data):
"""
Add tests from data loaded from the data file into the class
"""
for i, elem in enumerate(data):
if isinstance(data, dict):
key, value = elem, data[elem]
test_name = mk_test_name(name, key, i)
elif isinstance(data, list):
value = elem
test_name = mk_test_name(name, value, i)
if isinstance(value, dict):
add_test(cls, test_name, test_name, func, **value)
else:
add_test(cls, test_name, test_name, func, value)
def _is_primitive(obj):
"""Finds out if the obj is a "primitive". It is somewhat hacky but it works.
"""
return not hasattr(obj, '__dict__')
def _get_test_data_docstring(func, value):
"""Returns a docstring based on the following resolution strategy:
1. Passed value is not a "primitive" and has a docstring, then use it.
2. In all other cases return None, i.e the test name is used.
"""
if not _is_primitive(value) and value.__doc__:
return value.__doc__
else:
return None
def ddt(cls):
"""
Class decorator for subclasses of ``unittest.TestCase``.
Apply this decorator to the test case class, and then
decorate test methods with ``@data``.
For each method decorated with ``@data``, this will effectively create as
many methods as data items are passed as parameters to ``@data``.
The names of the test methods follow the pattern
``original_test_name_{ordinal}_{data}``. ``ordinal`` is the position of the
data argument, starting with 1.
For data we use a string representation of the data value converted into a
valid python identifier. If ``data.__name__`` exists, we use that instead.
For each method decorated with ``@file_data('test_data.json')``, the
decorator will try to load the test_data.json file located relative
to the python file containing the method that is decorated. It will,
for each ``test_name`` key create as many methods in the list of values
from the ``data`` key.
"""
for name, func in list(cls.__dict__.items()):
if hasattr(func, DATA_ATTR):
for i, v in enumerate(getattr(func, DATA_ATTR)):
test_name = mk_test_name(name, getattr(v, "__name__", v), i)
# 将用例描述信息改为用例数据的title字段
# 原代码test_data_docstring = _get_test_data_docstring(func, v)
test_data_docstring = v['title']
if hasattr(func, UNPACK_ATTR):
if isinstance(v, tuple) or isinstance(v, list):
add_test(
cls,
test_name,
test_data_docstring,
func,
*v
)
else:
# unpack dictionary
add_test(
cls,
test_name,
test_data_docstring,
func,
**v
)
else:
add_test(cls, test_name, test_data_docstring, func, v)
delattr(cls, name)
elif hasattr(func, FILE_ATTR):
file_attr = getattr(func, FILE_ATTR)
process_file_data(cls, name, func, file_attr)
delattr(cls, name)
return cls

View File

@ -0,0 +1,21 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/5 20:42
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
def login_check(username=None, passwd=None):
"""
登录校验的函数
:param username:
:param passwd:
:return: dict type
"""
if username != None and passwd != None:
if username == 'flora' and passwd == '1234567Az':
return {'code': 0, 'msg': '登录成功'}
else:
return {'code': 1, 'msg': '账号或者密码不正确'}
else:
return {'code': 1, 'msg': '账号和密码不能为空'}

View File

@ -0,0 +1,59 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 18:58
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import openpyxl
import os
# 从excel表格中读取数据
def login_data():
# 获取excel的路径
data_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'casesData2.xlsx')
# 将指定的excel文件加载为一个workbook对象
work_book = openpyxl.load_workbook(data_path)
# 选中工作簿中的表单对象
sheet_name = work_book['casesData']
# 按行读取表格中所有数据
excel_data = list(sheet_name.rows)
# 定义两个空列表来接收数据
data_key = []
data_value = []
# 定义一个列表来接收用例数据
cases_data = []
is_first_line = True
for line in excel_data:
# 如果是第一行数据就将每个单元格数据追加到列表data_key中
if is_first_line:
is_first_line = False
for column in line:
data_key.append(column.value)
continue
# 将剩余行数据中每个单元格数据追加到列表data_value中
is_first_column = True
for column in line:
# 如果是第一列则直接追加到列表data_value中
if is_first_column:
data_value.append(column.value)
is_first_column = False
continue
# 如果是剩余列则先获取单元格中的有效表达式字典再追加到data_value中
data_value.append(eval(column.value))
# 将两个列表打包成字典追加到保存用例数据的列表中
cases_data.append(dict(zip(data_key, data_value)))
# 清空列表data_value中的值否则每次打包的数据都会是相同的数据
data_value.clear()
return cases_data

View File

@ -0,0 +1,87 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/5 21:11
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
import os
"""
第一步创建测试套件
"""
# suite = unittest.TestSuite()
"""
第二步加载测试用例到测试套件
"""
# 第一种:通过测试用例类去加载
# from python27Class.homeWork.unitTest.homeWork03072020.testLogin import LoginTestCase
# loader = unittest.TestLoader()
# suite.addTest(loader.loadTestsFromTestCase(LoginTestCase))
# 第二种:通过测试用例模块去加载
# 用例加载器对象
# from python27Class.homeWork.unitTest.homeWork03072020 import testLogin
# loader=unittest.TestLoader()
# suite.addTest(loader.loadTestsFromModule(testLogin))
# 第三种:通过路径去加载所有的测试用例 (推荐这一种)
# 注意默认去找指定路径中test开头的模块中的测试用例
# path = os.path.dirname(os.path.abspath(__file__))
# loader = unittest.TestLoader()
# suite.addTest(loader.discover(path))
# 第四种:一条条去加载
# from python27Class.homeWork.unitTest.homeWork03072020.testLogin import LoginTestCase
# case1 = LoginTestCase('test_login')
# suite.addTest(case1)
# # 报错: AttributeError: 'LoginTestCase' object has no attribute 'test_login'
"""
综合第一步和第二步创建套件并加载用例
"""
path = os.path.dirname(os.path.abspath(__file__))
suite = unittest.defaultTestLoader.discover(path)
"""
第三步(1)执行测试套件中的用例, 控制台生成报告
"""
# 仅执行,未生成测试报告
# 创建测试运行程序
# runner = unittest.TextTestRunner()
# runner.run(suite)
# ----------------------------------------------
# 执行并生成测试报告
"""
第三步(2)使用BeautifulReport来执行测试套件中的用例并生成报告
# 2个参数报告描述用例名称报告文件名
report_dir用来指定报告的存放位置
"""
# from BeautifulReport import BeautifulReport
# beauty_report = BeautifulReport(suite)
# report_path = os.path.join(path, 'testReport')
# beauty_report.report('Login Function Test Report by flora',
# 'login_test_report_Beauty.html',
# report_dir=report_path)
# ----------------------------------------------
"""
第三步(3)使用HTMLTestRunner来生成测试报告
stream表示报告存放的位置以及写入的模式
title表示报告的标题
tester表示测试人员
description表示对测试报告的描述
"""
from HTMLTestRunner import HTMLTestRunner
report_path = os.path.join(path, 'testReport')
runner = HTMLTestRunner(stream=open(os.path.join(report_path, 'login_test_report_HTML.html'), 'wb'),
title='Login Function Test Report',
tester='flora.chen',
description='Version 1.0')
runner.run(suite)

View File

@ -0,0 +1,54 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/5 20:23
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
from python27Class.homeWork.unitTest.homeWork03072020.demo2.ddtNew import ddt, data
from python27Class.homeWork.unitTest.homeWork03072020.demo2.login import login_check
from python27Class.homeWork.unitTest.homeWork03072020.demo2.readExcel2 import login_data
"""
# 定义测试用例类必须继承unittest.TestCase
# 定义测试用例在测试用例类中每一个以test开头的方法就是一条用例
# unittest中测试用例执行的顺序是根据方法名按ASCII码进行排序的
# unittest中会自动根据用例方法执行的时候是否出现断言异常来评判用例执行是否通过
"""
@ddt
class LoginTestCase(unittest.TestCase):
# 第一步:准备用例数据
# 第二步:获取实际结果(调用功能函数,传入参数,获取实际结果)
# 第三步:断言(比对预期结果和实际结果)
# 方式一:直接定义列表作为测试数据
# cases_data = [
# {'title': '登录成功', 'expect_result': {'code': 0, 'msg': '登录成功'}, 'data': {'username': 'flora', 'passwd': '1234567Az'}},
# {'title': '账号不正确', 'expect_result': {"code": 1, "msg": "账号或者密码不正确"}, 'data': {'username': 'flora.chen', 'passwd': '1234567Az'}},
# {'title': '密码不正确', 'expect_result': {"code": 1, "msg": "账号或者密码不正确"}, 'data': {'username': 'flora', 'passwd': '1234567'}},
# {'title': '账号为空', 'expect_result': {"code": 1, "msg": "账号和密码不能为空"},'data': {'passwd': '1234567Az'}},
# {'title': '密码为空', 'expect_result': {"code": 1, "msg": "账号和密码不能为空"},'data': {'username': 'flora'}},
# ]
# 这里使用方式二从excel中读取用例数据
@data(*login_data())
def test_login_case(self, case_data):
# 参数准备
login_data = case_data['data']
# 预期结果准备
expect_result = case_data['expect_result']
# 获取实际结果
actual_result = login_check(**login_data)
# 断言
self.assertEqual(expect_result, actual_result)
if __name__ == '__main__':
login_test = LoginTestCase()
login_test.test_login_case(*login_test.cases_data)

View File

@ -0,0 +1,235 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Login Function Test Report</title>
<meta name="generator" content="HTMLTestRunner 0.8.2.2"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="http://libs.baidu.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<style type="text/css" media="screen">
body { font-family: Microsoft YaHei,Tahoma,arial,helvetica,sans-serif;padding: 20px; font-size: 120%; }
table { font-size: 100%; }
/* -- heading ---------------------------------------------------------------------- */
.heading {
margin-top: 0ex;
margin-bottom: 1ex;
}
.heading .description {
margin-top: 4ex;
margin-bottom: 6ex;
}
/* -- report ------------------------------------------------------------------------ */
#total_row { font-weight: bold; }
.passCase { color: #5cb85c; }
.failCase { color: #d9534f; font-weight: bold; }
.errorCase { color: #f0ad4e; font-weight: bold; }
.hiddenRow { display: none; }
.testcase { margin-left: 2em; }
</style>
</head>
<body >
<script language="javascript" type="text/javascript">
output_list = Array();
/*level 调整增加只显示通过用例的分类 --Findyou
0:Summary //all hiddenRow
1:Failed //pt hiddenRow, ft none
2:Pass //pt none, ft hiddenRow
3:All //pt none, ft none
*/
function showCase(level) {
trs = document.getElementsByTagName("tr");
for (var i = 0; i < trs.length; i++) {
tr = trs[i];
id = tr.id;
if (id.substr(0,2) == 'ft') {
if (level == 2 || level == 0 ) {
tr.className = 'hiddenRow';
}
else {
tr.className = '';
}
}
if (id.substr(0,2) == 'pt') {
if (level < 2) {
tr.className = 'hiddenRow';
}
else {
tr.className = '';
}
}
}
//加入【详细】切换文字变化 --Findyou
detail_class=document.getElementsByClassName('detail');
//console.log(detail_class.length)
if (level == 3) {
for (var i = 0; i < detail_class.length; i++){
detail_class[i].innerHTML="收起"
}
}
else{
for (var i = 0; i < detail_class.length; i++){
detail_class[i].innerHTML="详细"
}
}
}
function showClassDetail(cid, count) {
var id_list = Array(count);
var toHide = 1;
for (var i = 0; i < count; i++) {
//ID修改 点 为 下划线 -Findyou
tid0 = 't' + cid.substr(1) + '_' + (i+1);
tid = 'f' + tid0;
tr = document.getElementById(tid);
if (!tr) {
tid = 'p' + tid0;
tr = document.getElementById(tid);
}
id_list[i] = tid;
if (tr.className) {
toHide = 0;
}
}
for (var i = 0; i < count; i++) {
tid = id_list[i];
//修改点击无法收起的BUG加入【详细】切换文字变化 --Findyou
if (toHide) {
document.getElementById(tid).className = 'hiddenRow';
document.getElementById(cid).innerText = "详细"
}
else {
document.getElementById(tid).className = '';
document.getElementById(cid).innerText = "收起"
}
}
}
function html_escape(s) {
s = s.replace(/&/g,'&amp;');
s = s.replace(/</g,'&lt;');
s = s.replace(/>/g,'&gt;');
return s;
}
</script>
<div class='heading'>
<h1 style="font-family: Microsoft YaHei">Login Function Test Report</h1>
<p class='attribute'><strong>测试人员 : </strong> flora.chen</p>
<p class='attribute'><strong>开始时间 : </strong> 2020-03-07 20:11:50</p>
<p class='attribute'><strong>合计耗时 : </strong> 0:00:00</p>
<p class='attribute'><strong>测试结果 : </strong> 共 10通过 10通过率= 100.00%</p>
<p class='description'>Version 1.0</p>
</div>
<p id='show_detail_line'>
<a class="btn btn-primary" href='javascript:showCase(0)'>概要{ 100.00% }</a>
<a class="btn btn-danger" href='javascript:showCase(1)'>失败{ 0 }</a>
<a class="btn btn-success" href='javascript:showCase(2)'>通过{ 10 }</a>
<a class="btn btn-info" href='javascript:showCase(3)'>所有{ 10 }</a>
</p>
<table id='result_table' class="table table-condensed table-bordered table-hover">
<colgroup>
<col align='left' />
<col align='right' />
<col align='right' />
<col align='right' />
<col align='right' />
<col align='right' />
</colgroup>
<tr id='header_row' class="text-center success" style="font-weight: bold;font-size: 16px;">
<td>用例集/测试用例</td>
<td>总计</td>
<td>通过</td>
<td>失败</td>
<td>错误</td>
<td>详细</td>
</tr>
<tr class='passClass warning'>
<td>testLogin.LoginTestCase</td>
<td class="text-center">5</td>
<td class="text-center">5</td>
<td class="text-center">0</td>
<td class="text-center">0</td>
<td class="text-center"><a href="javascript:showClassDetail('c1',5)" class="detail" id='c1'>详细</a></td>
</tr>
<tr id='pt1_1' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_1: 登录成功</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt1_2' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_2: 账号不正确</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt1_3' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_3: 密码不正确</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt1_4' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_4: 账号为空</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt1_5' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_5: 密码为空</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr class='passClass warning'>
<td>testLogin2.LoginTestCase</td>
<td class="text-center">5</td>
<td class="text-center">5</td>
<td class="text-center">0</td>
<td class="text-center">0</td>
<td class="text-center"><a href="javascript:showClassDetail('c2',5)" class="detail" id='c2'>详细</a></td>
</tr>
<tr id='pt2_1' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_1: 登录成功</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt2_2' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_2: 账号不正确</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt2_3' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_3: 密码不正确</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt2_4' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_4: 账号为空</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt2_5' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_5: 密码为空</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='total_row' class="text-center active">
<td>总计</td>
<td>10</td>
<td>10</td>
<td>0</td>
<td>0</td>
<td>通过率100.00%</td>
</tr>
</table>
<div id='ending'>&nbsp;</div>
<div style=" position:fixed;right:50px; bottom:30px; width:20px; height:20px;cursor:pointer">
<a href="#"><span class="glyphicon glyphicon-eject" style = "font-size:30px;" aria-hidden="true">
</span></a></div>
</body>
</html>

View File

@ -0,0 +1,319 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/7 10:52
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
# -*- coding: utf-8 -*-
# This file is a part of DDT (https://github.com/datadriventests/ddt)
# Copyright 2012-2015 Carles Barrobés and DDT contributors
# For the exact contribution history, see the git revision log.
# DDT is licensed under the MIT License, included in
# https://github.com/datadriventests/ddt/blob/master/LICENSE.md
import inspect
import json
import os
import re
import codecs
from functools import wraps
try:
import yaml
except ImportError: # pragma: no cover
_have_yaml = False
else:
_have_yaml = True
__version__ = '1.2.2'
# These attributes will not conflict with any real python attribute
# They are added to the decorated test method and processed later
# by the `ddt` class decorator.
DATA_ATTR = '%values' # store the data the test must run with
FILE_ATTR = '%file_path' # store the path to JSON file
UNPACK_ATTR = '%unpack' # remember that we have to unpack values
index_len = 5 # default max length of case index
try:
trivial_types = (type(None), bool, int, float, basestring)
except NameError:
trivial_types = (type(None), bool, int, float, str)
def is_trivial(value):
if isinstance(value, trivial_types):
return True
elif isinstance(value, (list, tuple)):
return all(map(is_trivial, value))
return False
def unpack(func):
"""
Method decorator to add unpack feature.
"""
setattr(func, UNPACK_ATTR, True)
return func
def data(*values):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
"""
global index_len
index_len = len(str(len(values)))
return idata(values)
def idata(iterable):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
"""
def wrapper(func):
setattr(func, DATA_ATTR, iterable)
return func
return wrapper
def file_data(value):
"""
Method decorator to add to your test methods.
Should be added to methods of instances of ``unittest.TestCase``.
``value`` should be a path relative to the directory of the file
containing the decorated ``unittest.TestCase``. The file
should contain JSON encoded data, that can either be a list or a
dict.
In case of a list, each value in the list will correspond to one
test case, and the value will be concatenated to the test method
name.
In case of a dict, keys will be used as suffixes to the name of the
test case, and values will be fed as test data.
"""
def wrapper(func):
setattr(func, FILE_ATTR, value)
return func
return wrapper
def mk_test_name(name, value, index=0):
"""
Generate a new name for a test case.
It will take the original test name and append an ordinal index and a
string representation of the value, and convert the result into a valid
python identifier by replacing extraneous characters with ``_``.
We avoid doing str(value) if dealing with non-trivial values.
The problem is possible different names with different runs, e.g.
different order of dictionary keys (see PYTHONHASHSEED) or dealing
with mock objects.
Trivial scalar values are passed as is.
A "trivial" value is a plain scalar, or a tuple or list consisting
only of trivial values.
"""
# Add zeros before index to keep order
index = "{0:0{1}}".format(index + 1, index_len)
if not is_trivial(value):
return "{0}_{1}".format(name, index)
try:
value = str(value)
except UnicodeEncodeError:
# fallback for python2
value = value.encode('ascii', 'backslashreplace')
test_name = "{0}_{1}_{2}".format(name, index, value)
return re.sub(r'\W|^(?=\d)', '_', test_name)
def feed_data(func, new_name, test_data_docstring, *args, **kwargs):
"""
This internal method decorator feeds the test data item to the test.
"""
@wraps(func)
def wrapper(self):
return func(self, *args, **kwargs)
wrapper.__name__ = new_name
wrapper.__wrapped__ = func
# set docstring if exists
if test_data_docstring is not None:
wrapper.__doc__ = test_data_docstring
else:
# Try to call format on the docstring
if func.__doc__:
try:
wrapper.__doc__ = func.__doc__.format(*args, **kwargs)
except (IndexError, KeyError):
# Maybe the user has added some of the formating strings
# unintentionally in the docstring. Do not raise an exception
# as it could be that user is not aware of the
# formating feature.
pass
return wrapper
def add_test(cls, test_name, test_docstring, func, *args, **kwargs):
"""
Add a test case to this class.
The test will be based on an existing function but will give it a new
name.
"""
setattr(cls, test_name, feed_data(func, test_name, test_docstring,
*args, **kwargs))
def process_file_data(cls, name, func, file_attr):
"""
Process the parameter in the `file_data` decorator.
"""
cls_path = os.path.abspath(inspect.getsourcefile(cls))
data_file_path = os.path.join(os.path.dirname(cls_path), file_attr)
def create_error_func(message): # pylint: disable-msg=W0613
def func(*args):
raise ValueError(message % file_attr)
return func
# If file does not exist, provide an error function instead
if not os.path.exists(data_file_path):
test_name = mk_test_name(name, "error")
test_docstring = """Error!"""
add_test(cls, test_name, test_docstring,
create_error_func("%s does not exist"), None)
return
_is_yaml_file = data_file_path.endswith((".yml", ".yaml"))
# Don't have YAML but want to use YAML file.
if _is_yaml_file and not _have_yaml:
test_name = mk_test_name(name, "error")
test_docstring = """Error!"""
add_test(
cls,
test_name,
test_docstring,
create_error_func("%s is a YAML file, please install PyYAML"),
None
)
return
with codecs.open(data_file_path, 'r', 'utf-8') as f:
# Load the data from YAML or JSON
if _is_yaml_file:
data = yaml.safe_load(f)
else:
data = json.load(f)
_add_tests_from_data(cls, name, func, data)
def _add_tests_from_data(cls, name, func, data):
"""
Add tests from data loaded from the data file into the class
"""
for i, elem in enumerate(data):
if isinstance(data, dict):
key, value = elem, data[elem]
test_name = mk_test_name(name, key, i)
elif isinstance(data, list):
value = elem
test_name = mk_test_name(name, value, i)
if isinstance(value, dict):
add_test(cls, test_name, test_name, func, **value)
else:
add_test(cls, test_name, test_name, func, value)
def _is_primitive(obj):
"""Finds out if the obj is a "primitive". It is somewhat hacky but it works.
"""
return not hasattr(obj, '__dict__')
def _get_test_data_docstring(func, value):
"""Returns a docstring based on the following resolution strategy:
1. Passed value is not a "primitive" and has a docstring, then use it.
2. In all other cases return None, i.e the test name is used.
"""
if not _is_primitive(value) and value.__doc__:
return value.__doc__
else:
return None
def ddt(cls):
"""
Class decorator for subclasses of ``unittest.TestCase``.
Apply this decorator to the test case class, and then
decorate test methods with ``@data``.
For each method decorated with ``@data``, this will effectively create as
many methods as data items are passed as parameters to ``@data``.
The names of the test methods follow the pattern
``original_test_name_{ordinal}_{data}``. ``ordinal`` is the position of the
data argument, starting with 1.
For data we use a string representation of the data value converted into a
valid python identifier. If ``data.__name__`` exists, we use that instead.
For each method decorated with ``@file_data('test_data.json')``, the
decorator will try to load the test_data.json file located relative
to the python file containing the method that is decorated. It will,
for each ``test_name`` key create as many methods in the list of values
from the ``data`` key.
"""
for name, func in list(cls.__dict__.items()):
if hasattr(func, DATA_ATTR):
for i, v in enumerate(getattr(func, DATA_ATTR)):
test_name = mk_test_name(name, getattr(v, "__name__", v), i)
# 将用例描述信息改为用例数据的title字段
# 原代码test_data_docstring = _get_test_data_docstring(func, v)
test_data_docstring = v['title']
if hasattr(func, UNPACK_ATTR):
if isinstance(v, tuple) or isinstance(v, list):
add_test(
cls,
test_name,
test_data_docstring,
func,
*v
)
else:
# unpack dictionary
add_test(
cls,
test_name,
test_data_docstring,
func,
**v
)
else:
add_test(cls, test_name, test_data_docstring, func, v)
delattr(cls, name)
elif hasattr(func, FILE_ATTR):
file_attr = getattr(func, FILE_ATTR)
process_file_data(cls, name, func, file_attr)
delattr(cls, name)
return cls

View File

@ -0,0 +1,21 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/5 20:42
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
def login_check(username=None, passwd=None):
"""
登录校验的函数
:param username:
:param passwd:
:return: dict type
"""
if username != None and passwd != None:
if username == 'flora' and passwd == '1234567Az':
return {'code': 0, 'msg': '登录成功'}
else:
return {'code': 1, 'msg': '账号或者密码不正确'}
else:
return {'code': 1, 'msg': '账号和密码不能为空'}

View File

@ -0,0 +1,79 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/11 9:08
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import openpyxl
class HandleExcel:
"""
这是一个从excel中读取用例数据并将测试结果写回excel的类
"""
def __init__(self, filename, sheetname):
"""
实例属性
:param filename: excel文件的绝对路径
:param sheetname: excel中我们需要读取的表单的名称
"""
self.filename = filename
self.sheetname = sheetname
def read_data(self):
# 获取工作簿对象
wb = openpyxl.load_workbook(self.filename)
# 获取该工作簿的表单
sh = wb[self.sheetname]
# 获取所有行的数据
rows_data = list(sh.rows)
# 定义一个空列表cases_data来保存所有的用例数据
cases_data = []
# 获取表头将表头每个单元格中的数据值保存在列表title中
title = []
for i in rows_data[0]:
title.append(i.value)
# 获取剩余行的数据并将剩余行每个单元格的数据值保存在列表values中
for i in rows_data[1:]:
values = []
for j in i:
values.append(j.value)
# 将title跟每一行的values打包成字典并追加到cases_data列表中
cases_data.append(dict(zip(title, values)))
# 关闭保存excel文件
wb.save(self.filename)
# 将用例数据返回
return cases_data
def write_data(self, row, column, value):
"""
执行完测试用例后将测试结果写回到excel的类
:param row: 要写入的行
:param column: 要写入的列
:param value: 要写入的内容
:return:
"""
# 获取工作簿对象
wb = openpyxl.load_workbook(self.filename)
# 获取该工作簿的表单
sh = wb[self.sheetname]
# 在指定行列写入数据
sh.cell(row=row, column=column, value=value)
# 关闭保存excel文件
wb.save(self.filename)
if __name__ == '__main__':
excel = HandleExcel('loginCaseData.xlsx', 'loginData')
print(excel.read_data())
# excel.write_data(7, 5, 'flora')

View File

@ -0,0 +1,49 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/11 9:46
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import unittest
import os
import time
from BeautifulReport import BeautifulReport
from HTMLTestRunner import HTMLTestRunner
# # 创建测试套件
# suite = unittest.TestSuite()
#
# # 执行当前目录下所有的test开头的模块
# loader = unittest.TestLoader()
# case_path = os.path.dirname(os.path.abspath(__file__))
# suite.addTest(loader.discover(case_path))
# 创建并加载测试用例
case_path = os.path.dirname(os.path.abspath(__file__))
suite = unittest.defaultTestLoader.discover(case_path)
# 存放测试报告的路径
report_path = os.path.join(case_path, 'testReport')
# 获取当前时间
now_time = time.strftime('%Y-%m-%d %H_%M_%S')
# 定义测试报告的名称
report_name = 'login_' + now_time + '.html'
# # 使用BeautifulReport生成测试报告
br = BeautifulReport(suite)
br.report('Login Function Test Report by flora', report_name, report_dir=report_path)
# 使用HTMLTestRunner生成测试报告
# result_html = open(os.path.join(report_path, report_name), 'wb')
# runner = HTMLTestRunner(stream=result_html,
# title='Login Function Test Report',
# tester='flora.chen',
# description='Version 2.0'
# )
# runner.run(suite)
# result_html.close()

View File

@ -0,0 +1,66 @@
"""
=================================
Author: Flora Chen
Time: 2020/3/11 8:57
-_- -_- -_- -_- -_- -_- -_- -_-
=================================
"""
import os
import unittest
from python27Class.homeWork.unitTest.homeWork03102020.login import login_check
from python27Class.homeWork.unitTest.homeWork03102020.ddtNew import ddt, data
from python27Class.homeWork.unitTest.homeWork03102020.readExcel import HandleExcel
@ddt
class TestLoginCase(unittest.TestCase):
"""
这是用来测试登录功能的类
"""
# 实例化HandleExcel类
excel_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'loginCaseData.xlsx')
excel = HandleExcel(excel_path, 'loginData')
# 调用HandleExcel类中的read_data()方法
cases_data = excel.read_data()
@data(*cases_data)
def test_login_case(self, case_data):
"""
这是用来测试登录功能的用例
:param case_data: 用例数据
:return:
"""
# 首先准备用例数据
login_data = eval(case_data['login_data'])
expect_result = eval(case_data['expect_result'])
# 调用login获取实际结果
actual_result = login_check(**login_data)
# 要写入的行
row = case_data['case_id'] + 1
# 要写入的列默认是excel用例数据的最后一列result列
column = len(case_data)
# 定义一个变量来接收测试结果
test_result = ''
# 捕获异常不管用例是通过还是未通过最终都将测试结果写入excel中
try:
self.assertEqual(expect_result, actual_result)
# 如果用例失败将未通过写回excel并抛出异常
except AssertionError as e:
test_result = '未通过'
raise e
# 如果用例通过将通过写回excel
else:
test_result = '通过'
finally:
self.excel.write_data(row=row, column=column, value=test_result)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,238 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Login Function Test Report</title>
<meta name="generator" content="HTMLTestRunner 0.8.2.2"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link href="http://libs.baidu.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="http://libs.baidu.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<style type="text/css" media="screen">
body { font-family: Microsoft YaHei,Tahoma,arial,helvetica,sans-serif;padding: 20px; font-size: 120%; }
table { font-size: 100%; }
/* -- heading ---------------------------------------------------------------------- */
.heading {
margin-top: 0ex;
margin-bottom: 1ex;
}
.heading .description {
margin-top: 4ex;
margin-bottom: 6ex;
}
/* -- report ------------------------------------------------------------------------ */
#total_row { font-weight: bold; }
.passCase { color: #5cb85c; }
.failCase { color: #d9534f; font-weight: bold; }
.errorCase { color: #f0ad4e; font-weight: bold; }
.hiddenRow { display: none; }
.testcase { margin-left: 2em; }
</style>
</head>
<body >
<script language="javascript" type="text/javascript">
output_list = Array();
/*level 调整增加只显示通过用例的分类 --Findyou
0:Summary //all hiddenRow
1:Failed //pt hiddenRow, ft none
2:Pass //pt none, ft hiddenRow
3:All //pt none, ft none
*/
function showCase(level) {
trs = document.getElementsByTagName("tr");
for (var i = 0; i < trs.length; i++) {
tr = trs[i];
id = tr.id;
if (id.substr(0,2) == 'ft') {
if (level == 2 || level == 0 ) {
tr.className = 'hiddenRow';
}
else {
tr.className = '';
}
}
if (id.substr(0,2) == 'pt') {
if (level < 2) {
tr.className = 'hiddenRow';
}
else {
tr.className = '';
}
}
}
//加入【详细】切换文字变化 --Findyou
detail_class=document.getElementsByClassName('detail');
//console.log(detail_class.length)
if (level == 3) {
for (var i = 0; i < detail_class.length; i++){
detail_class[i].innerHTML="收起"
}
}
else{
for (var i = 0; i < detail_class.length; i++){
detail_class[i].innerHTML="详细"
}
}
}
function showClassDetail(cid, count) {
var id_list = Array(count);
var toHide = 1;
for (var i = 0; i < count; i++) {
//ID修改 点 为 下划线 -Findyou
tid0 = 't' + cid.substr(1) + '_' + (i+1);
tid = 'f' + tid0;
tr = document.getElementById(tid);
if (!tr) {
tid = 'p' + tid0;
tr = document.getElementById(tid);
}
id_list[i] = tid;
if (tr.className) {
toHide = 0;
}
}
for (var i = 0; i < count; i++) {
tid = id_list[i];
//修改点击无法收起的BUG加入【详细】切换文字变化 --Findyou
if (toHide) {
document.getElementById(tid).className = 'hiddenRow';
document.getElementById(cid).innerText = "详细"
}
else {
document.getElementById(tid).className = '';
document.getElementById(cid).innerText = "收起"
}
}
}
function html_escape(s) {
s = s.replace(/&/g,'&amp;');
s = s.replace(/</g,'&lt;');
s = s.replace(/>/g,'&gt;');
return s;
}
</script>
<div class='heading'>
<h1 style="font-family: Microsoft YaHei">Login Function Test Report</h1>
<p class='attribute'><strong>测试人员 : </strong> flora.chen</p>
<p class='attribute'><strong>开始时间 : </strong> 2020-03-11 14:06:06</p>
<p class='attribute'><strong>合计耗时 : </strong> 0:00:00.112031</p>
<p class='attribute'><strong>测试结果 : </strong> 共 7通过 6失败 1通过率= 85.71%</p>
<p class='description'>Version 2.0</p>
</div>
<p id='show_detail_line'>
<a class="btn btn-primary" href='javascript:showCase(0)'>概要{ 85.71% }</a>
<a class="btn btn-danger" href='javascript:showCase(1)'>失败{ 1 }</a>
<a class="btn btn-success" href='javascript:showCase(2)'>通过{ 6 }</a>
<a class="btn btn-info" href='javascript:showCase(3)'>所有{ 7 }</a>
</p>
<table id='result_table' class="table table-condensed table-bordered table-hover">
<colgroup>
<col align='left' />
<col align='right' />
<col align='right' />
<col align='right' />
<col align='right' />
<col align='right' />
</colgroup>
<tr id='header_row' class="text-center success" style="font-weight: bold;font-size: 16px;">
<td>用例集/测试用例</td>
<td>总计</td>
<td>通过</td>
<td>失败</td>
<td>错误</td>
<td>详细</td>
</tr>
<tr class='failClass warning'>
<td>testLogin.TestLoginCase</td>
<td class="text-center">7</td>
<td class="text-center">6</td>
<td class="text-center">1</td>
<td class="text-center">0</td>
<td class="text-center"><a href="javascript:showClassDetail('c1',7)" class="detail" id='c1'>详细</a></td>
</tr>
<tr id='pt1_1' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_case_1: 登录成功</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt1_2' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_case_2: 账号不正确</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt1_3' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_case_3: 密码不正确</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt1_4' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_case_4: 账号为空</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt1_5' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_case_5: 密码为空</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='pt1_6' class='hiddenRow'>
<td class='passCase'><div class='testcase'>test_login_case_6: 账号和密码都为空</div></td>
<td colspan='5' align='center'><span class="label label-success success">通过</span></td>
</tr>
<tr id='ft1_7' class='none'>
<td class='failCase'><div class='testcase'>test_login_case_7: 失败的用例</div></td>
<td colspan='5' align='center'>
<!--默认收起错误信息 -Findyou
<button id='btn_ft1_7' type="button" class="btn btn-danger btn-xs collapsed" data-toggle="collapse" data-target='#div_ft1_7'>失败</button>
<div id='div_ft1_7' class="collapse"> -->
<!-- 默认展开错误信息 -Findyou -->
<button id='btn_ft1_7' type="button" class="btn btn-danger btn-xs" data-toggle="collapse" data-target='#div_ft1_7'>失败</button>
<div id='div_ft1_7' class="collapse in" align="left">
<pre>
ft1_7: Traceback (most recent call last):
File "E:\PycharmProject\ChyClass\python27Class\homeWork\unitTest\homeWork03102020\ddtNew.py", line 152, in wrapper
return func(self, *args, **kwargs)
File "E:\PycharmProject\ChyClass\python27Class\homeWork\unitTest\homeWork03102020\testLogin.py", line 53, in test_login_case
raise e
File "E:\PycharmProject\ChyClass\python27Class\homeWork\unitTest\homeWork03102020\testLogin.py", line 49, in test_login_case
self.assertEqual(expect_result, actual_result)
AssertionError: {'code': 2, 'msg': '账号和密码不能为空'} != {'code': 1, 'msg': '账号和密码不能为空'}
- {'code': 2, 'msg': '账号和密码不能为空'}
? ^
+ {'code': 1, 'msg': '账号和密码不能为空'}
? ^
</pre>
</div>
</td>
</tr>
<tr id='total_row' class="text-center active">
<td>总计</td>
<td>7</td>
<td>6</td>
<td>1</td>
<td>0</td>
<td>通过率85.71%</td>
</tr>
</table>
<div id='ending'>&nbsp;</div>
<div style=" position:fixed;right:50px; bottom:30px; width:20px; height:20px;cursor:pointer">
<a href="#"><span class="glyphicon glyphicon-eject" style = "font-size:30px;" aria-hidden="true">
</span></a></div>
</body>
</html>