有限狀態(tài)機(jī)(Finite-state machine, FSM)糊闽,又稱有限狀態(tài)自動(dòng)機(jī)轩缤,簡(jiǎn)稱狀態(tài)機(jī)酒繁,是表示有限個(gè)狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動(dòng)作等行為的數(shù)學(xué)模型。FSM是一種算法思想晚岭,簡(jiǎn)單而言,有限狀態(tài)機(jī)由一組狀態(tài)勋功、一個(gè)初始狀態(tài)坦报、輸入和根據(jù)輸入及現(xiàn)有狀態(tài)轉(zhuǎn)換為下一個(gè)狀態(tài)的轉(zhuǎn)換函數(shù)組成。現(xiàn)實(shí)世界中存在大量具有有限個(gè)狀態(tài)的系統(tǒng):鐘表系統(tǒng)狂鞋、電梯系統(tǒng)片择、交通信號(hào)燈系統(tǒng)、通信協(xié)議系統(tǒng)骚揍、正則表達(dá)式字管、硬件電路系統(tǒng)設(shè)計(jì)、軟件工程信不,編譯器等嘲叔,有限狀態(tài)機(jī)的概念就是來自于現(xiàn)實(shí)世界中的這些有限系統(tǒng)。
transitions是一個(gè)由Python實(shí)現(xiàn)的輕量級(jí)的抽活、面向?qū)ο蟮挠邢逘顟B(tài)機(jī)框架硫戈。
transitions最基本的用法如下:
- 先自定義一個(gè)類Matter
- 定義一系列狀態(tài)和狀態(tài)轉(zhuǎn)移(定義狀態(tài)和狀態(tài)轉(zhuǎn)移有多種方式,官網(wǎng)上給了最快速理解的一個(gè)例子)
- 初始化狀態(tài)機(jī)
4.獲取當(dāng)前的狀態(tài)或者進(jìn)行轉(zhuǎn)化
from transitions import Machine
class Matter(object):
pass
model = Matter()
#The states argument defines the name of states
states=['solid', 'liquid', 'gas', 'plasma']
# The trigger argument defines the name of the new triggering method
transitions = [
{'trigger': 'melt', 'source': 'solid', 'dest': 'liquid' },
{'trigger': 'evaporate', 'source': 'liquid', 'dest': 'gas'},
{'trigger': 'sublimate', 'source': 'solid', 'dest': 'gas'},
{'trigger': 'ionize', 'source': 'gas', 'dest': 'plasma'}]
machine = Machine(model=model, states=states, transitions=transitions, initial='solid')
# Test
print(model.state) # solid
model.melt()
print(model.state) # liquid
model.evaporate()
print(model.state)
上面那個(gè)例子是物體的幾個(gè)狀態(tài)的轉(zhuǎn)換下硕,如下圖:
當(dāng)然transitions庫(kù)還有更高階一點(diǎn)的用法丁逝,比如直接顯示出圖形,官網(wǎng)上是說可以用pygraphviz 來顯示卵牍,但是本身pygraphviz 在windows上有一些問題果港,所以沒有試驗(yàn)成功,等以下問題修復(fù)后準(zhǔn)備再次嘗試糊昙。
https://github.com/pytransitions/transitions/issues/258
可能有的同學(xué)好奇這個(gè)transitions庫(kù)對(duì)于我們測(cè)試有什么幫助呢辛掠?
大家還記得測(cè)試設(shè)計(jì)方法中有一種稱之為 狀態(tài)遷移法 么?其實(shí)在設(shè)計(jì)測(cè)試用例的時(shí)候释牺,需要在各種狀態(tài)之間遷移并且最好能夠做到隨機(jī)的處理萝衩。
這部分狀態(tài)遷移的測(cè)試用例在自動(dòng)化的時(shí)候,Transitions庫(kù)能在這方面對(duì)我們有一定的幫助没咙。
from transitions import Machine
class AModel(object):
def __init__(self):
self.sv = 0 # state variable of the model
self.conditions = { # each state
'sA': 0,
'sB': 3,
'sC': 6,
'sD': 0,
}
def poll(self):
if self.sv >= self.conditions[self.state]:
self.next_state() # go to next state
else:
getattr(self, 'to_%s' % self.state)() # enter current state again
def on_enter(self):
print('entered state %s' % self.state)
def on_exit(self):
print('exited state %s' % self.state)
# setup model and state machine
model = AModel()
# init transitions model
list_of_states = ['sA', 'sB', 'sC', 'sD']
machine = Machine(model=model, states=list_of_states, initial='sA',
ordered_transitions=True, before_state_change='on_exit',
after_state_change='on_enter')
# begin main
for i in range(0, 10):
print('iter is: ' + str(i) + " -model state is:" + model.state)
model.sv = i
model.poll()
上面這段代碼執(zhí)行的時(shí)候的效果如下:
iter is: 0 -model state is:sA
exited state sA
entered state sB
iter is: 1 -model state is:sB
exited state sB
entered state sB
iter is: 2 -model state is:sB
exited state sB
entered state sB
iter is: 3 -model state is:sB
exited state sB
entered state sC
iter is: 4 -model state is:sC
exited state sC
entered state sC
iter is: 5 -model state is:sC
exited state sC
entered state sC
iter is: 6 -model state is:sC
exited state sC
entered state sD
iter is: 7 -model state is:sD
exited state sD
entered state sA
iter is: 8 -model state is:sA
exited state sA
entered state sB
iter is: 9 -model state is:sB
exited state sB
entered state sC
Transitions庫(kù)的具體用法可以參照它的github項(xiàng)目(https://github.com/pytransitions/transitions),還有一些extensions也很有效的猩谊,這部分有時(shí)間以后會(huì)繼續(xù)研究。