行業測試數據-案例分享 一 總體介紹 “人類正從IT時代走向DT時代” 1.數據測試指的是檢查局部數據結構時為了保證臨時存儲在模塊內的數據在程式執行過程中完整、正確的過程。2.工程師開發完成後,常常需要製造大批量的偽數據,來測試數據中台的開發效果。例如在數倉開發中,會遇到需要在已構建的數倉模型(各種 ...
行業測試數據-案例分享
一 總體介紹
“人類正從IT時代走向DT時代”
1.數據測試指的是檢查局部數據結構時為了保證臨時存儲在模塊內的數據在程式執行過程中完整、正確的過程。2.工程師開發完成後,常常需要製造大批量的偽數據,來測試數據中台的開發效果。例如在數倉開發中,會遇到需要在已構建的數倉模型(各種表)中,導入一些測試數據,方便邏輯開發完之前進行開發和測試。亦或是自己有一些SQL邏輯需要測試,需要批量造一些假數據(幾百上千條,甚至幾十萬條)。
如何在造數過程中保障數據質量,優化數據產出
數據質量問題:數據一致性,數據完整性、數據準確性、數據唯一性、數據關聯性、數據及時性
數據準確性:用於分析和識別無效或者不准確的數據,不可靠的數據可能會導致嚴重的問題。數據唯一性:用於識別和度量重覆數據、冗餘數據,重覆數據是導致業務無法協同、流程無法追溯的重要因素,是需要解決的最基本的數據問題。數據完整性:唯一性約束不完整、參照不完整;數據條目不完整、數據記錄丟失或不可用;不完整的數據所能借鑒的價值就會大大降低,也是數據質量問題最為基礎和常見的問題。數據一致性:多源數據的數據模型不一致,例如:命名不一致、數據結構不一致、約束規則不一致。數據實體不一致,例如:數據編碼不一致、命名及含義不一致、分類層次不一致、生命周期不一致……。相同的數據有多個副本的情況下的數據不一致、數據內容衝突的問題。數據關聯性:數據關聯性問題是指存在數據關聯的數據關係缺失或錯誤,例如主外鍵關係、索引關係等。會直接影響數據分析的結果。數據及時性:能否在需要的時候獲到數據,數據的及時性與企業的數據處理速度及效率有直接的關係,是影響業務處理和管理效率的關鍵指標。
實時數據類:
源頭數據訂閱-》流式計算計算平臺-〉數據輸出線上存儲系統
2、 邏輯正確性:
本地測試:模擬實時數據流,校驗輸出結果是否正確
3、數據準確性:
本地邏輯校驗通過後,對真實數據進行校驗。把實時數據拖回ODPS,做離線的查詢、統計、對比
4、時效性:
關註日誌時間和表數據產生時間,不能與實際時間偏差太大
二 語言簡介
1.什麼是python
Python是一種開源的 、解析性的,面向對象的編程語言。
Python使用一種優雅的語法,可讀性強 Python支持類和多層繼承等的面向對象編程技術。
Python可運行在多種電腦平臺和操作系統中,如unix,windows,MacOS,ubuntu,OS/2等等
Python 標識符
在python里,標識符有字母、數字、下劃線組成。在python中,所有標識符可以包括英文、數字以及下劃線(_),但不能以數字開頭。python中的標識符是區分大小寫的。以下劃線開頭的標識符是有特殊意義的。以單下劃線開頭(_foo)的代表不能直接訪問的類屬性,需通過類提供的介面進行訪問,不能用"from xxx import *"而導入;以雙下劃線開頭的(foo)代表類的私有成員;以雙下劃線開頭和結尾的(foo)代表python里特殊方法專用的標識,如__init()代表類的構造函數。
Python保留字元
下麵的列表顯示了在Python中的保留字。這些保留字不能用作常數或變數,或任何其他標識符名稱。所有Python的關鍵字只包含小寫字母。
and exec notassert finally orbreak for passclass from printcontinue global raisedef if returndel import tryelif in whileelse is withexcept lambda yield
多行語句
Python語句中一般以新行作為為語句的結束符。但是我們可以使用斜杠( \)將一行的語句分為多行顯示。
語句中包含[], {} 或 () 括弧就不需要使用多行連接符。
Python 引號和註釋
2.Python 接收單引號(' ),雙引號(" ),三引號(''' """) 來表示字元串,引號的開始與結束必須的相同類型的。其中三引號可以由多行組成,編寫多行文本的快捷語法,常用語文檔字元串,在文件的特定地點,被當做註釋。
3.Python中單行註釋採用#開頭
python 中多行註釋使用三個單引號(''')或三個雙引號(""")
多個語句構成代碼組縮進相同的一組語句構成一個代碼塊,我們稱之代碼組。像if、while、def和class這樣的複合語句,首行以關鍵字開始,以冒號( : )結束,該行之後的一行或多行代碼構成代碼組。我們將首行及後面的代碼組稱為一個子句(clause)。
4.Python數據類型
準數據類型在記憶體中存儲的數據可以有多種類型。例如,person.s年齡作為一個數值存儲和他或她的地址是字母數字字元存儲。Python有一些標準類型用於定義操作上,他們和為他們每個人的存儲方法可能。Python有五個標準的數據類型:Numbers(數字)String(字元串)List(列表)Tuple(元組)Dictionary(字典)
Python數字數字數據類型用於存儲數值。他們是不可改變的數據類型,這意味著改變數字數據類型會分配一個新的對象。Python支持四種不同的數字類型:
int(有符號整型)
long(長整型[也可以代表八進位和十六進位])
float(浮點型)
complex(複數)
Python 支持四種不同的數值類型:整型(Int) - 通常被稱為是整型或整數,是正或負整數,不帶小數點。長整型(long integers) - 無限大小的整數,整數最後是一個大寫或小寫的L。浮點型(floating point real values) - 浮點型由整數部分與小數部分組成,浮點型也可以使用科學計數法表示(2.5e2 = 2.5 x 102 = 250)複數( (complex numbers)) - 複數由實數部分和虛數部分構成,可以用a + bj,或者complex(a,b)表示, 複數的實部a和虛部b都是浮點型。
Python字元串字元串或串(String)是由數字、字母、下劃線組成的一串字元。s="a1a2···an"(n>=0)它是編程語言中表示文本的數據類型。python的字串列表有2種取值順序:從左到右索引預設0開始的,最大範圍是字元串長度少1從右到左索引預設-1開始的,最大範圍是字元串開頭如果你的實要取得一段子串的話,可以用到變數[頭下標:尾下標],就可以截取相應的字元串,其中下標是從0開始算起,可以是正數或負數,下標可以為空表示取到頭或尾。比如:s = 'ilovepython's[1:5]的結果是love。
5.字元串類型的操作符
序列類型通用的操作符 in, not in, +,等
只適用於字元串的操作符格式化操作符 %
格式化字元 | 轉換方式 |
---|---|
%r | 優先用repr()函數進行字元串轉換 |
%s | 優先用str()函數進行字元串轉換 |
%d / %i | 轉換成有符號十進位數 |
%u | 轉換成無符號十進位數 |
%o | 轉換成無符號八進位數 |
%x / %X | 轉換成無符號十六進位數(x/X代表轉換後的大小寫) |
%e / %E | 轉換成科學計數法 |
%f / %F | 轉換成浮點數 |
%% | 輸出% |
當使用以冒號分隔的字元串,python返回一個新的對象,結果包含了以這對偏移標識的連續的內容,左邊的開始是包含了下邊界。上面的結果包含了s[1]的值l,而取到的最大範圍不包括上邊界,就是s[5]的值p。加號(+)是字元串連接運算符,星號(*)是重覆操作。
6.Python列表List(列表) 是 Python 中使用最頻繁的數據類型。列表可以完成大多數集合類的數據結構實現。它支持字元,數字,字元串甚至可以包含列表(所謂嵌套)。列表用[ ]標識。是python最通用的複合數據類型。看這段代碼就明白。列表中的值得分割也可以用到變數[頭下標:尾下標],就可以截取相應的列表,從左到右索引預設0開始的,從右到左索引預設-1開始,下標可以為空表示取到頭或尾。加號(+)是列表連接運算符,星號(*)是重覆操作。
7.Python元組元組是另一個數據類型,類似於List(列表)。元組用"()"標識。內部元素用逗號隔開。但是元組不能二次賦值,相當於只讀列表。
8.Python元字典字典(dictionary)是除列表以外python之中最靈活的內置數據結構類型。列表是有序的對象結合,字典是無序的對象集合。兩者之間的區別在於:字典當中的元素是通過鍵來存取的,而不是通過偏移存取。字典用"{ }"標識。字典由索引(key)和它對應的值value組成
Python數據類型轉換有時候,我們需要對數據內置的類型進行轉換,數據類型的轉換,你只需要將數據類型作為函數名即可。以下幾個內置的函數可以執行數據類型之間的轉換。這些函數返回一個新的對象,表示轉換的值。
9.條件和迴圈
條件表達式
Python條件語句是通過一條或多條語句的執行結果(True或者False)來決定執行的代碼塊。
Python程式語言指定任何非0和非空(null)值為true,0 或者 null為false。Python 編程中 if 語句用於控製程序的執行,基本形式為:if 判斷條件: 執行語句……else: 執行語句……
其中"判斷條件"成立時(非零),則執行後面的語句,而執行內容可以多行,以縮進來區分表示同一範圍。else 為可選語句,當需要在條件不成立時執行內容則可以執行相關語句
迴圈控制語句
迴圈控制語句可以更改語句執行的順序。Python支持以下迴圈控制語句:
break語句 在語句塊執行過程中終止迴圈,並且跳出整個迴圈。
continue語句 在語句塊執行過程中終止當前迴圈,跳出改次迴圈,執行下一次迴圈
pass語句 pass是空語句,是為了保持程式結構的完整性
迴圈表達式
Python的迴圈語句,程式在一般情況下是按順序執行的。編程語言提供了各種控制結構,允許更複雜的執行路徑。迴圈語句允許我們執行一個語句或語句組多次。
Python 迴圈語句實例
10.函數
Python 函數函數是組織好的,可重覆使用的,用來實現單一,或相關聯功能的代碼段。函數能提高應用的模塊性,和代碼的重覆利用率。你已經知道Python提供了許多內建函數,比如print()。但你也可以自己創建函數,這被叫做用戶自定義函數。
定義一個函數你可以定義一個由自己想要功能的函數,以下是簡單的規則:函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括弧()。任何傳入參數和自變數必須放在圓括弧中間。圓括弧之間可以用於定義參數。函數的第一行語句可以選擇性地使用文檔字元串—用於存放函數說明。函數內容以冒號起始,並且縮進。return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當於返回 None。
語法:
def functionname( parameters ):
"函數_文檔字元串"
function_suite
return [expression]
預設情況下,參數值和參數名稱是按函數聲明中定義的的順序匹配起來的。
實例:
以下為一個簡單的Python函數,它將一個字元串作為傳入參數,再列印到標準顯示設備上。
def printme( str ):
"列印傳入的字元串到標準顯示設備上"
print str
return
函數調用定義一個函數只給了函數一個名稱,指定了函數里包含的參數,和代碼塊結構。這個函數的基本結構完成以後,你可以通過另一個函數調用執行,也可以直接從Python提示符執行。如下實例調用了printme()函數:
!/usr/bin/python# -- coding: UTF-8 --
定義函數
def printme( str ):
"列印任何傳入的字元串"
print str
return # 調用函數printme("我要調用用戶自定義函數!")
printme("再次調用同一函數");
按值傳遞參數和按引用傳遞參數所有參數(自變數)在Python里都是按引用傳遞。如果你在函數里修改了參數,那麼在調用這個函數的函數里,原始的參數也被改變了。
!/usr/bin/python# -- coding: UTF-8 --
可寫函數說明
def changeme( mylist ):
mylist.append([1,2,3,4]);
print "函數內取值: ",
return # 調用changeme函數
mylist = [10,20,30];
changeme( mylist );
傳入函數的和在末尾添加新內容的對象用的是同一個引用。故輸出結果如下:
函數內取值: [10, 20, 30, [1, 2, 3, 4]]
函數外取值: [10, 20, 30, [1, 2, 3, 4]]
11.python高階函數map()函數接收兩個參數,一個是函數,一個是Iterable,map將傳入的函數依次作用到序列的每個元素,並把結果作為新的Iterator返回。reduce把一個函數作用在一個序列[x1, x2, x3, ...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:
!/usr/bin/python# -- coding: UTF-8 -- >>> from functools import reduce>>> def add(x, y):... return x + y...>>> reduce(add, [1, 3, 5, 7, 9])25
!/usr/bin/python# -- coding: UTF-8 -- >>> from functools import reduce>>> def fn(x, y):... return x * 10 + y...>>> reduce(fn, [1, 3, 5, 7, 9])13579
!/usr/bin/python# -- coding: UTF-8 -- # 可寫函數說明>>> def f(x):... return x * x...>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])>>> list(r)[1, 4, 9, 16, 25, 36, 49, 64, 81]mylist
!/usr/bin/python# -- coding: UTF-8 -- >>> from functools import reduce>>> def fn(x, y):... return x * 10 + y...>>> def char2num(s):... digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}... return digits[s]...>>> reduce(fn, map(char2num, '13579'))13579
filter()也接收一個函數和一個序列。和map()不同的是,filter()把傳入的函數依次作用於每個元素,然後根據返回值是True還是False決定保留還是丟棄該元素。
Python內置的sorted()函數就可以對list進行排序:>>> sorted([36, 5, -12, 9, -21])[-21, -12, 5, 9, 36]sorted()函數也是一個高階函數,它還可以接收一個key函數來實現自定義的排序,例如按絕對值大小排序:>>> sorted([36, 5, -12, 9, -21], key=abs)[5, 9, -12, -21, 36]>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)['about', 'bob', 'Credit', 'Zoo']要進行反向排序,不必改動key函數,可以傳入第三個參數reverse=True:>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)['Zoo', 'Credit', 'bob', 'about']
12.模塊
Python 模塊模塊讓你能夠有邏輯地組織你的Python代碼段。把相關的代碼分配到一個 模塊里能讓你的代碼更好用,更易懂。模塊也是Python對象,具有隨機的名字屬性用來綁定或引用。簡單地說,模塊就是一個保存了Python代碼的文件。模塊能定義函數,類和變數。模塊里也能包含可執行的代碼。
例子:一個叫做aname的模塊里的Python代碼一般都能在一個叫aname.py的文件中找到。下例是個簡單的模塊support.py。def print_func( par ): print "Hello : ", par return
import 語句想使用Python源文件,只需在另一個源文件里執行import語句,語法如下:import module1[, module2[,... moduleN]
當解釋器遇到import語句,如果模塊在當前的搜索路徑就會被導入。搜索路徑是一個解釋器會先進行搜索的所有目錄的列表。如想要導入模塊support.py,需要把命令放在腳本的頂端
!/usr/bin/python3# -- coding: UTF-8 -- # 導入模塊import support
現在可以調用模塊里包含的函數了
support.print_func("Zara")
實例輸出結果:Hello : Zara
From…import 語句Python的from語句讓你從模塊中導入一個指定的部分到當前命名空間中。語法如下:from modname import name1[, name2[, ... nameN]]例如,要導入模塊fib的fibonacci函數,使用如下語句:from fib import fibonacci這個聲明不會把整個fib模塊導入到當前的命名空間中,它只會將fib里的fibonacci單個引入到執行這個聲明的模塊的全局符號表。
From…import* 語句把一個模塊的所有內容全都導入到當前的命名空間也是可行的,只需使用如下聲明:from modname import *這提供了一個簡單的方法來導入一個模塊中的所有項目。然而這種聲明不該被過多地使用。
dir()函數dir()函數一個排好序的字元串列表,內容是一個模塊里定義過的名字。返回的列表容納了在一個模塊里定義的所有模塊,變數和函數。如下一個簡單的實例:
!/usr/bin/python# -- coding: UTF-8 -- # 導入內置math模塊import math
content = dir(math)
print content;
['doc', 'file', 'name', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log','log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
13.面向對象編程
Python 面向對象Python從設計之初就已經是一門面向對象的語言,正因為如此,在Python中創建一個類和對象是很容易的。本章節我們將詳細介紹Python的面向對象編程。如果你以前沒有接觸過面向對象的編程語言,那你可能需要先瞭解一些面向對象語言的一些基本特征,在頭腦裡頭形成一個基本的面向對象的概念,這樣有助於你更容易的學習Python的面向對象編程。接下來我們先來簡單的瞭解下麵向對象的一些基本特征。
面向對象技術簡介:
類(Class): 用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例。類變數:類變數在整個實例化的對象中是公用的。類變數定義在類中且在函數體之外。類變數通常不作為實例變數使用。數據成員:類變數或者實例變數用於處理類及其實例對象的相關的數據。方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆蓋(override),也稱為方法的重寫。實例變數:定義在方法中的變數,只作用於當前實例的類。繼承:即一個派生類(derived class)繼承基類(base class)的欄位和方法。繼承也允許把一個派生類的對象作為一個基類對象對待。例如,有這樣一個設計:一個Dog類型的對象派生自Animal類,這是模擬"是一個(is-a)"關係(例圖,Dog是一個Animal)。實例化:創建一個類的實例,類的具體對象。方法:類中定義的函數。對象:通過類定義的數據結構實例。對象包括兩個數據成員(類變數和實例變數)和方法。
類的創建於實例化
使用class語句來創建一個新類,class之後為類的名稱並以冒號結尾,類的幫助信息可以通過ClassName.__doc__查看。class_suite 由類成員,方法,數據屬性組成。
!/usr/bin/python# -- coding: UTF-8 --
class Employee:
'所有員工的基類'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print "Total Employee %d" % Employee.empCount
def displayEmployee(self):
print "Name : ", self.name, ", Salary: ", self.salary
empCount變數是一個類變數,它的值將在這個類的所有實例之間共用。你可以在內部類或外部類使用Employee.empCount訪問。第一種方法__init__()方法是一種特殊的方法,被稱為類的構造函數或初始化方法,當創建了這個類的實例時就會調用該方法
要創建一個類的實例,你可以使用類的名稱,並通過__init__方法接受參數。
"創建 Employee 類的第一個對象"emp1 = Employee("Zara", 2000)"創建 Employee 類的第二個對象"emp2 = Employee("Manni", 5000)
訪問屬性您可以使用點(.)來訪問對象的屬性。使用如下類的名稱訪問類變數:
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount
可以添加,刪除,修改類的屬性,如下所示:
emp1.age = 7 # 添加一個 'age'
屬性emp1.age = 8 # 修改 'age' 屬性
del emp1.age # 刪除 'age' 屬性
也可以使用以下函數的方式來訪問屬性
getattr(obj, name[, default]) : 訪問對象的屬性。
hasattr(obj,name) : 檢查是否存在一個屬性。
setattr(obj,name,value) : 設置一個屬性。如果屬性不存在,會創建一個新屬性。
delattr(obj, name) : 刪除屬性。
hasattr(emp1, 'age') # 如果存在 'age' 屬性返回 True。
getattr(emp1, 'age') # 返回 'age' 屬性的值
setattr(emp1, 'age', 8) # 添加屬性 'age' 值為 8
delattr(empl, 'age') # 刪除屬性 'age'
Python內置類屬性
dict : 類的屬性(包含一個字典,由類的數據屬性組成)
doc :類的文檔字元串__name__: 類名
module: 類定義所在的模塊(類的全名是'main.className',如果類位於一個導入模塊mymod中,那麼className.module 等於 mymod)
bases : 類的所有父類構成元素(包含了一個由所有父類組成的元組)
14.異常處理
異常即是一個事件,該事件會在程式執行過程中發生,影響了程式的正常執行。一般情況下,在Python無法正常處理程式時就會發生一個異常。異常是Python對象,表示一個錯誤。當Python腳本發生異常時我們需要捕獲處理它,否則程式會終止執行。
捕捉異常可以使用try/except語句。
try/except語句用來檢測try語句塊中的錯誤,從而讓except語句捕獲異常信息並處理。如果你不想在異常發生時結束你的程式,只需在try里捕獲它。語法:以下為簡單的try....except...else的語法:
try:<語句>
#運行別的代碼
except <名字>:
<語句>
#如果在try部份引發了'name'異常
except <名字>,<數據>:
<語句>
#如果引發了'name'異常,獲得附加的數據
else:<語句>
#如果沒有異常發生
15.場景案例:
python的faker模塊
在軟體需求、開發、測試過程中,有時候需要使⽤⼀些測試數據,針對這種情況,我們⼀般要麼使⽤已有的系統數據,要麼需要⼿動製造⼀些數據。由於現在的業務系統數據多種多樣,千變萬化。在⼿動製造數據的過程中,可能需要花費⼤量精⼒和⼯作量,此項⼯作既繁複⼜容易出錯,⽐如要構造⼀批⽤戶三要素(姓名、⼿機號、⾝份證)、構造⼀批銀⾏卡數據、或構造⼀批地址通訊錄等。
Faker是什麼Faker是⼀個Python包,主要⽤來創建偽數據,使⽤Faker包,⽆需再⼿動⽣成或者⼿寫隨機數來⽣成數據,只需要調⽤Faker提供的⽅法,即可完成數據的⽣成。
pyhon的faker模塊比較簡單,從faker模塊倒入這個類,然後實例化這個類就可以使用了
from faker import Faker
faker=Faker()
name=faker.name()
address=faker.address()
print(name)
print(address)
輸出信息
Ashely Love
074 Lee Suilt 644
faker常用模塊舉例:
- fake.address():完整地址,比如海南省成市豐都深圳路p座 425541
- fake.street_address():街道+地址,比如興城路A座
- fake.street_name():街道名,比如宜都街
- fake.city_name():城市名,比如蘭州
- fake.city():城市,比如蘭州市
- fake.province():省份名,比如陝西省
- fake.postcode():郵編
- fake.country():國家
- fake.company():公司名,比如惠派國際公司信息有限公司
- fake.company_suffix():公司名尾碼(公司性質),比如網路有限公司
- fake.company_prefix():公司名首碼,比如鑫博騰飛
faker模塊 完整案例:
from faker import Faker
import xlwt
import random
faker = Faker("zh_CN")
gender = ["男", "女"]
education = ["小學", "初中", "高中", "大專", "大學本科", "研究生"]
asset = ["私人銀行級:>800萬元", "七星級:600~800萬元", "六星級:100~600萬元", "五星級:20~100萬元",
"四星級:5~20萬元", "三星級:1~20萬元", "二星級:<1萬元", "準星級:0"]
risk_tolerance = ["A1(保守型)", "A2(穩健型)", "A3(平衡型)", "A4(成長型)", "A5(進取型)"]
wb = xlwt.Workbook(encoding='utf-8')
sheet1 = wb.add_sheet('客戶')
head_data = ['姓名', '性別', '年齡', '學歷', '電話號', '資產等級', '風險承受能力等級']
for head in head_data:
sheet1.write(0, head_data.index(head), head)
for i in range(1, 100):
sheet1.write(i, 0, faker.name())
sheet1.write(i, 1, random.choice(gender))
sheet1.write(i, 2, random.randint(18, 70))
sheet1.write(i, 3, random.choice(education))
sheet1.write(i, 4, faker.phone_number())
sheet1.write(i, 5, random.choice(asset))
sheet1.write(i, 6, random.choice(risk_tolerance))
wb.save('客戶.xls')