python behave學(xué)習(xí)筆記 - feature testing

Feature Testing Layout

要讓behave工作起來需要下面三種類型的文件

  • 由非技術(shù)人員 BA/Sponsor等編寫的 feature files , 這些文件包含著應(yīng)用的場景行為
  • 一個(gè) step 目錄。這個(gè)目錄下面包含著scenario對應(yīng)的測試代碼
  • environmental control文件。這個(gè)是optional的
    • environment.py里面包含著關(guān)于run before after steps scenarios features等testing hook代碼

一個(gè)可執(zhí)行的最小feature目錄為

features/
features/everything.feature
features/steps/
features/steps/steps.py

最小為一個(gè)features目錄下面一個(gè)feature文件和一個(gè)steps目錄。steps里面包含了測試代碼。

一個(gè)更復(fù)雜的目錄為

features/
features/signup.feature
features/login.feature
features/account_details.feature
features/environment.py
features/steps/
features/steps/website.py
features/steps/utils.py

behave命令執(zhí)行

behave是靈活的,我們通過執(zhí)行帶有不同選項(xiàng)的命令來幫助behave找到feature文件,然后來執(zhí)行指定的文件

  • 當(dāng)執(zhí)行behave 時(shí), behave會(huì)從當(dāng)前目錄下尋找”features”子目錄,然后從中讀取feature文件
  • 當(dāng)執(zhí)行behave ./features,給behave傳遞features目錄所在路徑,behave會(huì)從中讀取至少一個(gè) name.feature 文件和一個(gè)叫 steps 的目錄。對于environment.py, 如果有的話,必須是和 steps 目錄在同一個(gè)目錄下
  • 當(dāng)執(zhí)行behave ./features/BookInformationAPITest.feature 給behave傳遞了一個(gè)指定的feature file,behave就會(huì)執(zhí)行指定的這個(gè)feature
  • 也可以給behave傳遞a directory containing your feature files。 behave的工作方式和上述方法類似

behave -v (-v verbose)可以看到更詳細(xì)的behave行為

Gherkin: Feature Testing Language

behave的features文件是由一種叫Gherkin的語言編寫的并且被命名為 name.feature

在理想情況下,這些feature files是有項(xiàng)目內(nèi)的非技術(shù)人員比如需求方使用自然語言來編寫。feature files有兩個(gè)目的,一個(gè)是作為正式文檔 ,二是支持自動(dòng)化測試

feature files的編寫非常自由靈活,但是還是有一些好的準(zhǔn)則可以堅(jiān)持:

  • 行結(jié)尾終止聲明
  • spaces或tabs都可以作為縮進(jìn)
  • 縮進(jìn)都會(huì)被忽略,但是縮進(jìn)是一個(gè)用來展示文本結(jié)構(gòu)的好辦法
  • 大部分的行要以關(guān)鍵字為開頭。Keywords: Feature, Scenario, Given

在文件的任何地方都可以使用 “#”來進(jìn)行注釋

Features

Features是由Scenarios來組成。Feature還可以加上description,background和tag,不過這些都是可選的。

最簡單的feature形式為

Feature: feature name

  Scenario: some scenario
      Given some condition
       Then some result is expected.

把description background tag都加上后,feature形式為

@tags @tag
Feature: feature name
  description
  further description

  Background: some requirement of this test
    Given some setup condition
      And some other setup action

  Scenario: some scenario
      Given some condition
       When some action is taken
       Then some result is expected.

  Scenario: some other scenario
      Given some other condition
       When some action is taken
       Then some other result is expected.

Feature name應(yīng)該為待測feature的合理描述的標(biāo)題

description

description是optional的,可以用來澄清任何潛在的confusions或是scope issue

Background

background是由一些step組成,這些step和scenarios里面的一樣。Background允許你給feature中的scenario加一些context。Background的執(zhí)行是在feature文件中所有的scenario之前,不過是在所有before hooks之后。

一個(gè)feature文件只有一個(gè)background。ackground必須在scenario或是scenario outline之前定義好。background經(jīng)常被用來做一些setup的事情,比如登陸一個(gè)頁面或是設(shè)置好數(shù)據(jù)庫

使用background的好實(shí)踐:

  • 不要用”Background’來設(shè)置較為復(fù)雜的狀態(tài)除非客戶要求
  • 保持”Background”短小精煉。如果Background大于4行,我們就可以把一些無關(guān)的細(xì)節(jié)挪到high level的steps
  • 使得“Background”栩栩如生,通俗易懂。可以使用豐富的名稱和描述來講述一個(gè)故事。
  • 保持scenario不會(huì)很長,也不能太多。不然Background會(huì)執(zhí)行很多遍

Scenarios

Scenarios描述了需要測試的產(chǎn)品行為。Scenario是由一系列steps組成。這些steps典型的形式是”given some condition” “then we expect some test will pass"

scenario最簡單的形式為

Scenario: we have some stock when we open the store
  Given that the store has just opened
  Then we should have items for sale.

如果有需要的話,and或是but都可以加到scenario里面,放在given when then之后

Scenario: Replaced items should be returned to stock
  Given that a customer buys a blue garment
    and I have two blue garments in stock
    but I have no red garments in stock
    and three black garments in stock.
   When he returns the garment for a replacement in black,
   then I should have three blue garments in stock
    and no red garments in stock,
    and two black garments in stock.

一個(gè)比較好的實(shí)踐是一個(gè)scenario就測試一個(gè)行為或是一種desired outcome

Scenario Outlines

當(dāng)對于同一個(gè)場景有著很多不同的期待輸入條件和輸出結(jié)果,我們可以使用scenario outline來做數(shù)據(jù)驅(qū)動(dòng),這樣可以重用scenario中的step

一個(gè)outline包含定義在step中的關(guān)鍵字,這些關(guān)鍵字會(huì)被表格中的數(shù)據(jù)來代替。一個(gè)scenario outline可以有多個(gè)example tables

Scenario Outline: Blenders
   Given I put <thing> in a blender,
    when I switch the blender on
    then it should transform into <other thing>

 Examples: Amphibians
   | thing         | other thing |
   | Red Tree Frog | mush        |

 Examples: Consumer Electronics
   | thing         | other thing |
   | iPhone        | toxic waste |
   | Galaxy Nexus  | toxic waste |

behave會(huì)跑example table里面的每一行。每一行的數(shù)據(jù)會(huì)去替代step里面尖括號(hào)定義的<thing> <other thing>

注意尖括號(hào)里的名字必須和表格頭的名字一致。

python step implementation如下

from behave   import given, when, then
from hamcrest import assert_that, equal_to
from blender  import Blender

@given('I put "{thing}" in a blender')
def step_given_put_thing_into_blender(context, thing):
    context.blender = Blender()
    context.blender.add(thing)

@when('I switch the blender on')
def step_when_switch_blender_on(context):
    context.blender.switch_on()

@then('it should transform into "{other_thing}"')
def step_then_should_transform_into(context, other_thing):
    assert_that(context.blender.result, equal_to(other_thing))

把<thing>作為參數(shù)傳入方法里面

Steps

每個(gè)step都會(huì)占據(jù)一行。并且以下面五個(gè)關(guān)鍵字中的一個(gè)來開頭:

  • given
  • when
  • then
  • and
  • but

通常來講這些關(guān)鍵字都應(yīng)該是Title Case就是首字母大寫的形式,部分語言還是支持只有全小寫

step的描述不應(yīng)該包含太多關(guān)于測試機(jī)制的細(xì)節(jié)

比如下面

Given a browser client is used to load the URL "http://website.example/website/home.html"

就應(yīng)該變?yōu)?/p>

Given we are looking at the home page

Steps的實(shí)現(xiàn)是由python寫的測試代碼組成,python的模塊“name.py”會(huì)被放在”steps”文件夾下。python模塊的文件命名是沒有規(guī)定的。所有在”steps”下面的文件都會(huì)被behave引入

Given

givens的目的是在用戶或外部系統(tǒng)對系統(tǒng)進(jìn)行交互之前,使系統(tǒng)處于一個(gè)可知的狀態(tài)。在givens中要避免涉及用戶交互的操作。
在use case中,givens可以被理解為前置條件precondition。也可以在Given中使用table來設(shè)置一些數(shù)據(jù)

When

whens的目的是描述用戶或是外部系統(tǒng)施展的關(guān)鍵行為。這個(gè)交互行為會(huì)引起系統(tǒng)狀態(tài)的變化

Then

thens的目的是觀察結(jié)果。這個(gè)觀察的結(jié)果應(yīng)該與feature描述的用戶價(jià)值business value/benefit相關(guān)聯(lián)。這個(gè)結(jié)果也應(yīng)該是一個(gè)系統(tǒng)產(chǎn)生的

具體的結(jié)果而不是對用戶不可見,埋藏得很深的結(jié)果。對用戶不可見的結(jié)果也許會(huì)沒有business value。比如我們應(yīng)該多驗(yàn)證用戶看得見的結(jié)果而不是去數(shù)據(jù)庫里面找結(jié)果

我們還可以使用And But來組織steps

Scenario: Multiple Givens
  Given one thing
  Given an other thing
  Given yet an other thing
   When I open my eyes
   Then I see something
   Then I don't see something else

可以寫為

Scenario: Multiple Givens
  Given one thing
    And an other thing
    And yet an other thing
   When I open my eyes
   Then I see something
    But I don't see something else

這兩種寫法對behave都是一樣的

Step Data

Steps除了given when then,還允許包含像文本text和表格table樣的數(shù)據(jù)。所以一個(gè)step可以包含自己的texttable,這就是Step Data

Scenario Outline values的一個(gè)替代方法就是使用<name>在Step data text或是table中

Text

任何在step中使用三個(gè)雙引號(hào)包括的文本就是Step data中的text

Scenario: some scenario
  Given a sample text loaded into the frobulator
     """
     Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
     eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
     enim ad minim veniam, quis nostrud exercitation ullamco laboris
     nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
     reprehenderit in voluptate velit esse cillum dolore eu fugiat
     nulla pariatur. Excepteur sint occaecat cupidatat non proident,
     sunt in culpa qui officia deserunt mollit anim id est laborum.
     """
 When we activate the frobulator
 Then we will find it similar to English

注意非第一行的whitespace數(shù)不能比第一行少。

在測試代碼中,我們使用Context.text來獲取這段text。Context.text也可以在每一個(gè)step function中傳遞使用。

第一個(gè)step定義的text是可以在scenario后面的step中的context中使用。在候選step中定義的text會(huì)overwrite之前step中的text。

Table

我們可以把一個(gè)表格數(shù)據(jù)賦予給一個(gè)step,只需要通過簡單的輸入,縮進(jìn)即可。當(dāng)我們想把一系列的數(shù)據(jù)賦值給一個(gè)model
的時(shí)候,這個(gè)Table特別有用

整個(gè)表格有兩個(gè) vertical bar “|“ 來區(qū)別列。任何在列和vertical bar之間的whitespace會(huì)被刪除

Scenario: some scenario
  Given a set of specific users
     | name      | department  |
     | Barry     | Beer Cans   |
     | Pudey     | Silly Walks |
     | Two-Lumps | Silly Walks |

 When we count the number of people in each department
 Then we will find two people in "Silly Walks"
  But we will find one person in "Beer Cans"

在測試代碼中,我們使用Context.table來獲取這段table。Context.table也可以在每一個(gè)step function中傳遞使用。測試代碼中,我們使用如下

@given('a set of specific users')
def step_impl(context):
    for row in context.table:
        model.add_user(name=row['name'], department=row['department'])

Tags

feature file中可以使用tag功能。tag功能可以讓behave實(shí)現(xiàn)選擇性的執(zhí)行feature

tag可以作用于feature,scenario和scenario outline。作用于feature的tag也會(huì)作用于feature下的scenario或scenario outlines

tag使用修飾符的樣式作用于feature/scenario/scenario outlines,多個(gè)tag之間可以使用whitespace來進(jìn)行間隔

For example:

@wip @slow
Feature: annual reporting
  Some description of a slow reporting system.

or

@wip
@slow
Feature: annual reporting
  Some description of a slow reporting system.

Controlling Your Test Run With Tags 我們可以使用tag來選擇性的執(zhí)行測試
Feature: Fight or flight
  In order to increase the ninja survival rate,
  As a ninja commander
  I want my ninjas to decide whether to take on an
  opponent based on their skill levels

  @slow
  Scenario: Weaker opponent
    Given the ninja has a third level black-belt
    When attacked by a samurai
    Then the ninja should engage the opponent

  Scenario: Stronger opponent
    Given the ninja has a third level black-belt
    When attacked by Chuck Norris
    Then the ninja should run for his life

對于上面這個(gè)feature file,

  • 如果運(yùn)行 behave —tags=slow 就只會(huì)運(yùn)行標(biāo)記了slow的Scenario Weaker opponent
  • 如果運(yùn)行 behave —tags=-slow,就會(huì)運(yùn)行沒有標(biāo)記slow的Scenarios

一個(gè)常用的場景是使用@wip來處理正在開發(fā)中的scenario或feature,使用behave —tags=wip來運(yùn)行這個(gè)正在開發(fā)的feature

在命令行中tag的用法:

  • 如果我們執(zhí)行behave —tags=slow,slow1 只要被tag為slow或slow1的scenario被執(zhí)行
  • 如果我們執(zhí)行behave —tags=slow —tags=slow1 只要被tag為slow并且slow1的scenario被執(zhí)行

tags與environment.py的互動(dòng)

  • 如果一個(gè)feature或是scenario被skip了,那么相應(yīng)的before_和after_都不會(huì)執(zhí)行
  • environment.py中各方法中的feature/scenario對象都有tags屬性,這個(gè)屬性是列出了所有tag名稱的列表
  • environment.py中的before_tag和after_tag。如果這兩個(gè)方法被傳入了”slow”,那么在執(zhí)行被tag為slow的scenario之前,這兩個(gè)方法會(huì)被調(diào)用

for example,部分scenario被tag為@browser,則我們可以使用feature.tags來查看tag有沒有browser.這樣做,我們可以指定哪些feature需要執(zhí)行這個(gè)before_和after_

def before_feature(context, feature):
    model.init(environment='test')
    if 'browser' in feature.tags:
        context.server = simple_server.WSGIServer(('', 8000))
        context.server.set_app(web_app.main(environment='test'))
        context.thread = threading.Thread(target=context.server.serve_forever)
        context.thread.start()
        context.browser = webdriver.Chrome()

def after_feature(context, feature):
    if 'browser' in feature.tags:
        context.server.shutdown()
        context.thread.join()
        context.browser.quit()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 基本概念 behave要被執(zhí)行,需要運(yùn)行在滿足下面兩種情況的目錄下 有feature files。這個(gè)featur...
    做測試的DanteYu閱讀 16,456評論 0 7
  • 從某種意義上來看,世間一切,都是遇見。就像, 冷遇見暖,就有了雨; 春遇見冬, 有了歲月; 天遇 見地, 有了永恒...
    相約遇見閱讀 153評論 0 0
  • 大腦程序使用說明書 微信號(hào) how13355789267 歡迎加好友交流 暗號(hào):商學(xué)院 跨年夜智商程序裝上了,但使...
    精英之門閱讀 452評論 1 4
  • 我的公眾號(hào)是轉(zhuǎn)角遇到更好的自己,我也曾對我朋友說過,我感覺我的生命從30歲才剛剛開始,30歲之前太過懵懂,不知道自...
  • 學(xué)習(xí)財(cái)商第二天,感觸自己的人生過的太無知啦!而為無知付出的代價(jià)就是活到了現(xiàn)在這個(gè)模樣!財(cái)商的學(xué)習(xí)刻不容緩!而且,孩...
    莫有青草閱讀 168評論 0 0

友情鏈接更多精彩內(nèi)容