uniset2-testsuiteの抂芁-機胜テスト甚の小さなバむク。 パヌト2



最初の郚分は、可胜性の抂芁でした。 そしお、このパヌトでは、どのテストむンタヌフェむスが既に実装されおいるか、独自のテストむンタヌフェむスを远加する方法に぀いお怜蚎したす。

どちらかずいえば、ここに蚘事の最初の郚分ぞのリンクがありたす

珟圚、uniset2-testsuiteは3぀のむンタヌフェむスをサポヌトしおいたす。


むンタヌフェむスタむプ=「uniset」


最初の郚分で曞いたように、 uniset2-testsuite党䜓は、最初はlibunisetを䜿甚しおプロゞェクトをテストするために開発されたした 。 したがっお、 type =“ uniset”は、開発された最初のメむンむンタヌフェむスです。 ナニセットプロゞェクトでは、䞻な芁玠は「センサヌ」であり、䞀意の識別子数倀ですが、文字列名を䜿甚できたすず、蚭定たたは受信できる倀がありたす。 したがっお、テストシナリオでは、すべおがこれらのセンサヌずその倀のチェックを䞭心に展開したす。 ここで説明されたアルゎリズムを実装する簡単なスクリプトの䟋です 。

<?xml version = '1.0' encoding = 'utf-8'?> <TestScenario> <TestList type="uniset"> <test name="Processing" comment="  "> <action set="OnControl_S=1" comment="  ' '"/> <check test="CmdLoad_C=1" comment="  ''"/> <check test="CmdUnload_C=0" comment="  ''"/> <check test="Level_AS>=90" comment=" .." timeout="15000"/> <check test="CmdLoad_C=0" comment="  ''"/> <check test="CmdUnload_C=1" comment="  ''"/> <check test="Level_AS<=10" comment=" .." timeout="15000"/> </test> <test name="Stopped" comment="  "> <action set="OnControl_S=0" comment="  ' '"/> <check test="CmdLoad_C=0" comment=" ''  " holdtime="3000"/> <check test="CmdUnload_C=0" comment=" ''  " holdtime="3000"/> <check test="Level_AS<=80" comment="  " holdtime="10000"/> </test> </TestList> </TestScenario> 


むンタヌフェむスタむプ=「modbus」


このむンタヌフェヌスは、暙準のModbus TCPプロトコルを䜿甚しおテスト䞭のシステムず通信できるため、広範囲の䜿甚にずっおより興味深いものです 。 これを䜿甚したテストシナリオは次のずおりです。

 <?xml version = '1.0' encoding = 'utf-8'?> <TestScenario type="modbus"> <Config> <aliases> <item type="modbus" alias="mb1" mbslave="localhost:2048" default="1"/> <item type="modbus" alias="mb2" mbslave="localhost:2049"/> </aliases> </Config> <TestList > <test name="Test simple read"> <check test="0x10!=0"/> <check test="0x24:0x04!=0"/> <check test="0x24!=0"/> <check test="0x1@0x02:0x02!=0" config="mb2"/> <check test="0x24:0x06!=0"/> </test> <test name="Test simple write"> <action set="0x25=10"/> <action set="0x25:0x10=10"/> <action set="0x25@0x02=10" config="mb2"/> <action set="0x25@0x02:0x05=10" config="mb2"/> </test> <test name="Test other 'check'"> <check test="0x20=0x20" timeout="1000" check_pause="100"/> <check test="0x20=0x20"/> </test> <test name="Test 'great'"> <action set="109=10"/> <check test="109>=5"/> <check test="109>=10"/> </test> <test name="Test 'less'"> <action set="109=10"/> <check test="109<=11"/> <check test="109<=10"/> </test> <test name="Test other 'action'"> <action set="20@2=1,21@0x02:5=1,103@2:0x10=12" config="mb2"/> </test> </TestList> </TestScenario> 

最初に、 構成セクションで、䜜業が実行される2぀のノヌドのパラメヌタヌが定矩されたす。 条件付きで、それらにはmb1およびmb2ずいう名前が割り圓おられたす。 それらの1぀がデフォルトずしお割り圓おられたすdefault = "1" 。 したがっお、テキストのどこでも、パラメヌタヌconfig = ".."が指定されおいない堎合、デフォルトのノヌドが䜿甚されたす。
テスト蚘録圢匏自䜓は次のようになりたす。
"mbreg@mbaddr:mbfunc:nbit:vtype"
どこで
mbadrr 、 mbfunc 、 nbit 、およびvtypeフィヌルドはオプションであり、デフォルト倀があるこずに泚意しおください。
その結果、このむンタヌフェむスを䜿甚するず、倚くのデバむスを操䜜するためのテストスクリプトを䜜成できたす。 たずえば、䞀郚のテストリグを管理しお、テストアクションをデバむスに送信し、その反応を確認できたす。 これはすべお、Modbus TCPプロトコルに準拠しおいたす。これは、ACSだけでなく、ACSで䜿甚されるデバむスのほがすべおのメヌカヌによっおサポヌトされおいたす。

むンタヌフェむスタむプ=「snmp」


このむンタヌフェむスは、SNMPプロトコルを介しおテスト察象のシステムで動䜜するように蚭蚈されおいたす。
いく぀かの実装の詳现
Pythonモゞュヌルpysnmp、netsnmpに基づいた実装がいく぀かありたした。 しかし、最終的には、さたざたなプラットフォヌムのさたざたなバヌゞョンで発生した問題により、
より倚くの「オヌク」゜リュヌション。 ぀たり、 net-snmp-clientsファミリヌのナヌティリティぞの呌び出しの䜿甚ずpopenによる結果の凊理。 逆説的に聞こえるかもしれたせんが、このメ゜ッドは玔粋なpythonモゞュヌルを䜿甚するよりも「ポヌタブル」であるこずが刀明したした。

snmpを䜿甚したテストケヌスの䟋を以䞋に瀺したす。
 <?xml version="1.0" encoding="utf-8"?> <TestScenario type="snmp"> <Config> <aliases> <item type="snmp" alias="snmp1" snmp="conf/snmp.xml" default="1"/> <item type="snmp" alias="snmp2" snmp="conf/snmp2.xml"/> </aliases> </Config> <TestList> <test name="SNMP read tests" comm="  snmp"> <check test="uptime@node1>1" comment="Uptime"/> <check test="uptimeName@node2>=1" comment=" " config="snmp2"/> </test> <test name="SNMP: FAIL READ" ignore_failed="1"> <check test="sysServ2@node2>=1" comment="fail read test" config="snmp2"/> </test> <test name="SNMP write tests" comm="  snmp"> <action set="sysName@ups3=10" comment="save sysName"/> <action set="sysServ2@ups3=10" comment="save sysServ"/> </test> <test name="SNMP: FAIL WRITE" ignore_failed="1"> <action set="sysServ2@node1=10" comment="FAIL SAVE TEST"/> </test> </TestList> </TestScenario> 

このむンタヌフェむスを䜿甚するには、特別な構成ファむルが必芁です。これは、 Configセクションに瀺されおいたす  snmp = ".." 。
SNMPスクリプトのSnmp.xml構成ファむル
 <?xml version='1.0' encoding='utf-8'?> <SNMP> <Nodes defaultProtocolVersion="2c" defaultTimeout='1' defaultRetries='2' defaultPort='161'> <item name="node1" ip="192.94.214.205" comment="UPS1" protocolVersion="2" timeout='1' retries='2'/> <item name="node2" ip="test.net-snmp.org" comment="UPS2"/> <item name="node3" ip="10.16.11.3" comment="UPS3"/> </Nodes> <MIBdirs> <dir path="conf/" mask="*.mib"/> <dir path="conf2/" mask="*.mib"/> </MIBdirs> <Parameters defaultReadCommunity="demopublic" defaultWriteCommunity="demoprovate"> <item name="uptime" OID="1.3.6.1.2.1.1.3.0" r_community="demopublic"/> <item name="uptimeName" ObjectName="sysUpTime.0"/> <item name="bstatus" OID="1.3.6.1.2.1.33.1.2.1.0" ObjectName="BatteryStatus"/> <item name="btime" OID=".1.3.6.1.2.1.33.1.2.2.0" ObjectName="TimeOnBattery"/> <item name="bcharge" OID=".1.3.6.1.2.1.33.1.2.4.0" ObjectName="BatteryCharge"/> <item name="sysName" ObjectName="sysName.0" w_community="demoprivate" r_community="demopublic"/> </Parameters> </SNMP> 


Nodesセクションは、亀換が行われるノヌドデバむスのリストを蚭定したす。 この堎合、次のパラメヌタヌを蚭定できたす。
[ ノヌド]セクションで盎接、すべおのノヌドのデフォルトパラメヌタを蚭定できたす。

MIBdirsセクションでは、mibファむルを含むディレクトリが蚭定され、OIDの正確性がチェックされたす。

Parametersセクションでは、テストに参加するパラメヌタヌのリストを蚭定したす。

OIDパラメヌタヌずObjectNameパラメヌタヌは亀換可胜です。 䞡方のパラメヌタヌが指定されおいる堎合、OIDが䜿甚されたす。 [ パラメヌタ]セクションで、すべおのノヌドのデフォルトパラメヌタを盎接蚭定できたす。


1぀のシナリオで耇数のむンタヌフェむスを䜿甚する


䟋を瀺したす。
 <?xml version="1.0" encoding="utf-8"?> <TestScenario> <Config> <aliases> <item type="uniset" alias="u" confile="configure.xml" default="1"/> <item type="modbus" alias="mb" mbslave="localhost:2048"/> <item type="snmp" alias="snmp" snmp="conf/snmp.xml"/> </aliases> </Config> <RunList after_run_pause="5000"> ... </RunList> <TestList> <test name="check: Equal test"> <action set="111=10"/> <check test="111=10"/> <check test="uptime@node1>1" config="snmp"/> <check test="0x10!=0" config="mb"/> </test> </TestList> </TestScenario> 

぀たり チェックごずに、 config = "aliasname"を蚭定しお、䜿甚するむンタヌフェむスを指定できたす。

むンタヌフェヌスを実装する方法


入門


基本的なむンタヌフェむスの䜜業䞭に、uniset2-testsuiteに埋め蟌むためのテストむンタヌフェむスの最小APIに関するビゞョンが圢成されたした。 そしお、䞻な機胜に぀いおは2぀の機胜を実装するだけで十分であるこずがわかりたした たあ、ほが 
  def get_value(self, name, context): ... def set_value(self, name, value, context): ... 

これは単玔なアむデアに基づいおいたす。 テストシナリオを芋るず、䞀般的に、チェックたたはアクションは次のように蚘述できるこずがわかりたす。
heck="[NAME]=[VALUE]" 。
「=」の代わりに、実際にはこれらの1぀が[=、>、> =、<、<= ,! =]である堎合がありたす。
぀たり チェックするパラメヌタヌの名前ずしお特定の[NAME]がありたす。 そしお、特定のむンタヌフェヌスはそれを解析する方法を知っおいたす。 [VALUE]がありたす-これは、結果を比范する倀たたは蚭定する倀です。 その結果、uniset2-testsuiteは、NAMEおよびVALUEのテストを解析するタスクを匕き受け、特定のむンタヌフェむス実装のget_valueたたはset_value関数を呌び出したす。 同時に、むンタヌフェむス自䜓は、[NAME]フィヌルドで䜜業が実行されるパラメヌタヌの暗号化方法を担圓したす。 䟋

぀たり むンタヌフェヌス開発者は、 NAMEのどのフォヌマットを遞択するかを決定したす。
珟圚の実装では、 timeout 、 check_time 、 holdtimeなどのテストケヌスパラメヌタがuniset2-testsuiteレベルで凊理されるこずに留意するこずが重芁です。 したがっお、テストで<check test="varname=34" timeout="15000" check_time="3000"/>ず瀺されおいる堎合、これはget_valuevarname関数がタむムアりトが期限切れになるたで3秒ごずに呌び出されるこずを意味したす34の倀が取埗されたす。
もう1぀の重芁な制限は、珟圚の実装では、[VALUE]が数倀ずしおのみサポヌトされおいるこずです。 実際、「任意の型」 基本的に文字列 をサポヌトするためにリメむクするこずはそれほど難しくありたせん。VALUEサポヌトを数倀ずしお実装する必芁はありたせんでした。 型compareのチェックがあるこずを思い出させおください 。これにより、数倀ではなく、別のパラメヌタヌの倀ず比范できたす。

構成


各むンタヌフェヌス自䜓が、動䜜に必芁な構成パラメヌタヌを決定したす。 uniset2-testsuiteでは、それらを蚘述するためのConfig / aliasesセクションが提䟛されたす。ここでは、パラメヌタヌをxmlプロパティずしお曞き蟌むこずができたす。 むンタヌフェヌスを䜜成するず、構成ノヌドが圌に転送され、そこから必芁なものすべおが考慮されたす。 䜙分なものすべおを定矩する必芁がある堎合、たずえば、構成ノヌドのsnmpむンタヌフェヌスで、構成ファむルsnmp.xmlを取埗する堎所のみを決定でき、むンタヌフェヌスが機胜するために必芁なものはすべおそこですでに定矩されおいたす。 同様に、たずえばmodbusむンタヌフェヌスの堎合、デバむスずの通信甚にIPずポヌトを定矩するだけで十分であり、これらのパラメヌタヌはConfigセクションに盎接曞き蟌たれたす。

プラグむンむンタヌフェむスをダりンロヌドする


むンタヌフェヌスのロヌドは、単玔な原則に基づいおいたす。 ディレクトリ ' plugins.d 'があり、そこからすべおのむンタヌフェヌスがロヌドされたす。 「システム」ディレクトリがあり、プラグむンはテストが実行されおいる珟圚のディレクトリのplugins.dサブディレクトリでも怜玢されたす。 したがっお、ナヌザヌはテストが配眮されおいる堎所にプラグむンを配眮するだけで、プラグむンは自動的に取埗されたす。
むンタヌフェヌスの各実装は、個別のpythonファむルずしお䜜成されたす。このファむルには、 uts_plugin_name関数が含たれおいる必芁がありたす。 たずえば、SNMPむンタヌフェむスでは次のようになりたす
 def uts_plugin_name(): return "snmp" 

その結果、むンタヌフェむス自䜓のロヌドは次のメカニズムに基づいおいたす。
 .. <Config> <aliases> <item type="uniset" alias="u" confile="configure.xml" default="1"/> <item type="modbus" alias="mb" mbslave="localhost:2048"/> <item type="snmp" alias="snmp" snmp="conf/snmp.xml"/> </aliases> </Config> ... 

テストスクリプトの凊理を開始するず、uniset2-testsuiteは䜿甚可胜なプラグむンのリストを名前でコンパむルし、 plugins.dディレクトリからロヌドしたす。 枡すずき次
type =“ xxxx”はConfigセクションを調べ、察応するむンタヌフェヌスが怜玢されたす。
特別な関数を呌び出すものを䜜成するには
xmlノヌドが枡されるuts_create_from_xml(xmlConfNode)
パラメヌタずしお。 さらに、むンタヌフェヌスの䜜成ずその初期化をすでに実装しおいたす。
芁するに
 uts_plugin_name() -       type="..." uts_create_from_xml(xmlConfNode) -    


構成パラメヌタヌの怜蚌


むンタヌフェむスを実装するには、2぀の関数set_valueずget_valueのみを実装すれば十分であるず䞊蚘で曞きたした。 実際、さらに2぀実装するこずが望たしいただし、必須ではない
  def validate_parameter(self, name): ... def validate_configuration(self): ... 

これらは、-check-scenarioモヌドの堎合に必芁です。テストモヌドの正確性が実際に実行されずにチェックされる堎合。 validate_parameter- 名前パラメヌタヌを怜蚌するために呌び出されたす。 そしお、テスト内の各テストに察しお呌び出されるこずに泚意しおください。 validate_configurationは、テスト党䜓の構成パラメヌタヌを確認するために1回呌び出されたす。 たずえば、snmp-interfaceでは、ノヌドの可甚性、およびmibファむルによるOIDずObjectNameの有効性を確認したす察応するディレクトリがどこにあるかが瀺されおいる堎合。

実装


さお、最埌に、実装に着きたした。 実䟋ずしおどのむンタヌフェむスを実装するかを考えお、可胜なむンタヌフェむスの「最も普遍的な」、぀たり、チェックずしおスクリプトを実行するむンタヌフェむスを開発するこずにしたした。 これを「スクリプト」ず呌びたす。 「スクリプト」ずいう蚀葉は、bashだけでなく、「実行できる」すべおを意味するこずをすぐに泚意したいず思いたす。 なぜなら テストごずにシェルを介しおプログラムを実際に実行したす。

だから。
たず、NAMEの圢匏を考え出す必芁がありたす䞊蚘を参照。 少し考えお、 正盎に蚀っお、詊しおみたずころ 、この単玔な圢匏になりたした。
  <test name="check scripts"> <check test="scriptname.sh >= VALUE" params="param1 param2 param3" ../> <check test="../myscritps/scriptname.sh >= VALUE" params="param1 param2 param3" ../> .. </test> 

フォヌマット怜玢に぀いお
最初に、GETリク゚ストのような圢匏を䜜成したかった scriptname?param1¶m2¶m3.
しかし、xmlがあるずいう制限に遭遇したした。 そしお、「  」をそのたた䜿甚するこずはできたせん。 「」アンプずしお蚘述されおいる堎合のみ。 。 もちろん、それはすべおの䟿利さをすでに無効にしおいる。


぀たり in test = ".."スクリプトの名前が曞き蟌たれたすパスを指定できたす。 なぜなら 結局のずころ、スクリプトにパラメヌタヌを枡したいため、特別なフィヌルド拡匵 params = "..."を導入したす 。

次に、結果を取埗する方法を理解する必芁がありたす。 なぜなら プログラムが0を返すこずは受け入れられたす-成功の堎合、倱敗の堎合は「れロではない」堎合、結果ずしお戻りコヌドを䜿甚するこずは、良い考えではないようです。 最終的に、プログラムが結果を含む特別なマヌカヌを暙準出力に出力するのが最も簡単な方法であるず刀断したした。 ぀たり 䞀方では、プログラムが独自のメッセヌゞを衚瀺するこずを犁止しおいたせんが、他方では、それから結果を取埗する必芁がありたす。 マヌカヌは次の圢匏の行になりたす TEST_SCRIPT_RESULT: VALUE

぀たり スクリプトを実行し、出力でマヌカヌをキャッチしお、そこから結果を切り取りたす。 ええ、はい、これ以䞊良いものは思い぀きたせん。

次の質問ぱラヌ凊理です。 ここではすべおが暙準です。 戻りコヌド= 0の堎合、゚ラヌ。 ゚ラヌの詳现ずしお、stderrのプログラムによっお衚瀺されたすべおのものを䜿甚したす。

グロヌバルむンタヌフェヌス蚭定パラメヌタヌ 今のずころ、単玔なむンタヌフェヌスには必芁ないず考えおいたす。 しかし、私は䟋えば1぀をしたした。

これで物語の終わりです。 どうした


次に、実装に進みたす...

モゞュヌルをロヌドするには、2぀のグロヌバル関数uts_create_from_xml..ずuts_plugin_nameを実装する必芁がありたす。
圌らは簡単です
 def uts_create_from_xml(xmlConfNode): """   :param xmlConfNode: xml-   :return:   UTestInterface """ return UTestInterfaceScripts(xmlConfNode=xmlConfNode) def uts_plugin_name(): return "scripts" 



むンタヌフェむス自䜓は、基本クラスUTestInterfaceから継承し、必芁な機胜を実装する必芁がありたす。 最初に、UTestInterface.pyクラスがどのように芋えるかを瀺したす。
UTestInterface.py
 #!/usr/bin/env python # -*- coding: utf-8 -*- from TestSuiteGlobal import * class UTestInterface(): """  """ def __init__(self, itype, **kwargs): self.itype = itype self.ignore_nodes = False def set_ignore_nodes(self, state): """ set ignore 'node' for tests (id@node) :param state: TRUE or FALSE """ self.ignore_nodes = state def get_interface_type(self): return self.itype def get_conf_filename(self): return '' def validate_parameter(self, name): """ Validate test parameter (id@node) :param name: parameter from <check> or <action> :return: [ RESULT, ERROR ] """ return [False, "(validateParam): Unknown interface.."] def validate_configuration(self): """ Validate configuration parameters (check-scenario-mode) :return: [ RESULT, ERROR ] """ return [False, "(validateConfiguration): Unknown interface.."] def get_value(self, name): raise TestSuiteException("(getValue): Unknown interface..") def set_value(self, name, value, supplier_id): raise TestSuiteException("(setValue): Unknown interface...") 



メむン関数get_value(self, name, context)実装するこずから始めget_value(self, name, context) 。
名前が枡されたす-私たちの堎合、これは基本的にスクリプトの名前です。
ただし、远加のparamsフィヌルドが導入されおいるため、同様に凊理する必芁がありたす。
远加のフィヌルドに到達するために、このような䟿利なパラメヌタヌをcontextずしお䜿甚したす 。 ドキュメントに他に興味深いものが曞かれおいたすが、そうでないかもしれないずいう事実を考慮しお、珟圚のテストのxmlノヌドを匕き出したすそしお䟋倖をスロヌしたす。
 def get_value(self, name, context): xmlnode = None if 'xmlnode' in context: xmlnode = context['xmlnode'] if not xmlnode: raise TestSuiteException("(scripts:get_value): Unknown xmlnode for '%s'" % name) ... 

䟿宜䞊、名前ずコンテキストを入力ずしお受け取り、 scriptnameずparametersを返す別の関数圢匏が埌で倉曎されるかどうかを匷調したした。

ここにありたす
parse_name
  @staticmethod def parse_name(name, context): """   : <check test="scriptname=XXX" params="param1 param2 param3" .../> :param name:   (     scriptname) :param context: :return: [scriptname, parameters] """ if 'xmlnode' in context: xmlnode = context['xmlnode'] return [name, uglobal.to_str(xmlnode.prop("params"))] return [name, ""] 


次に、get_valueは

完党に実装するだけです
get_value
 def get_value(self, name, context): xmlnode = None if 'xmlnode' in context: xmlnode = context['xmlnode'] if not xmlnode: raise TestSuiteException("(scripts:get_value): Unknown xmlnode for '%s'" % name) scriptname, params = self.parse_name(name, context) if len(scriptname) == 0: raise TestSuiteException("(scripts:get_value): Unknown script name for '%s'" % name) test_env = None if 'environment' in context: test_env = context['environment'] s_out = '' s_err = '' cmd = scriptname + " " + params try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=test_env, close_fds=True, shell=True) s_out = p.stdout.read(self.max_read) s_err = p.stderr.read(self.max_read) retcode = p.wait() if retcode != 0: emessage = "SCRIPT RETCODE(%d) != 0. stderr: %s" % (retcode, s_err.replace("\n", " ")) raise TestSuiteException("(scripts:get_value): %s" % emessage) except subprocess.CalledProcessError, e: raise TestSuiteException("(scripts:get_value): %s for %s" % (e.message, name)) if xmlnode.prop("show_output"): print s_out ret = self.re_result.findall(s_out) if not ret or len(ret) == 0: return None lst = ret[0] if not lst or len(lst) < 1: return None return uglobal.to_int(lst) 


少し説明。

スクリプトを実行するために、環境倉数をスクリプトに枡すこずもできたした。 これは、スクリプトに関するドキュメントのセクションにありたす。
繰り返したすが、コンテキストから環境倉数を含む蟞曞を取埗したす test_env = context['environment']

実装に2぀の远加パラメヌタヌshow_output = "1"を远加するこずを蚱可したした-これはチェックレベルパラメヌタヌです。 スクリプトがstdoutに衚瀺するすべおの画面ぞの出力を含める。 デフォルトでは、スクリプトは出力を無効にしお実行されたす。 そしお、入力した2番目のパラメヌタヌはグロヌバルなmax_read蚭定です。これは、結果を取埗するために読み取る必芁がある出力の最初のバむト数を決定したす。 たず、グロヌバル蚭定の䜿甚方法を瀺す必芁がありたした。 第二に、読み取り甚のバッファを制限するこずは良い考えだず思いたした。 さらに、サむズが0以䞋に蚭定されおいる堎合は、すべお実行できたす。
リタヌンコヌドの凊理で、コヌドがnullでない堎合、゚ラヌテキストずしおstderrを䜿甚したす同じ行に沿っお䜜成したす。
正芏衚珟を䜿甚したParsimの結果。
现郚
この堎合、実行䞭のプログラムの完了を埅っおいるこずがわかりたす。 ぀たり プログラムは非垞に簡朔で、
すぐに終了したす。 それでも、プログラムが「䜕時間も続けお」動䜜した堎合は奇劙です。 䞀方、タむムアりトによっおプログラムを匷制終了するこずも可胜です。

むンタヌフェむスをテストするには、 plugins.dディレクトリを䜜成し、そこにモゞュヌルを配眮したす。 たた、小さなテストを曞く
むンタヌフェむスをテストするテスト
 <?xml version="1.0" encoding="utf-8"?> <TestScenario> <Config> <environment> <item name="MyTEST_VAR1" value="MyTEST_VALUE1"/> <item name="MyTEST_VAR2" value="MyTEST_VALUE2"/> <item name="MyTEST_VAR3" value="MyTEST_VALUE3"/> </environment> <aliases> <item type="scripts" alias="s" default="1"/> </aliases> </Config> <TestList type="scripts"> <test name="Test run script" ignore_failed="1"> <check test="./test-script.sh != 10" params="--param1 3 --param2 4" timeout="2000"/> <check test="./test-script.sh = 100" params="param1=3,param2=4"/> <check test="./test-script-negative-number.sh = -20" show_output="1"/> <check test="./test-script-longtime.sh = 100" timeout="3000"/> <check test="./test-script-error.sh > 10"/> </test> </TestList> </TestScenario> 


Configセクションでは、デフォルトのむンタヌフェむスタむプが「scripts」であるこずが瀺されおいるこずに泚意しおください。TestListタグでは、スクリプト党䜓がこのタむプであるこずも瀺されおいたす。
スクリプトに加えお、次のような指定されたbashスクリプトを䜜成するこずを忘れないでください。
test-script.sh
 #!/bin/sh echo "TEST SCRIPT: $*" echo "SHOW OUTOUT..." echo "TEST_SCRIPT_RESULT: 100" 


同時に、環境倉数を導出しおそれらを調べたす
test-script-negative-number.sh
 #!/bin/sh echo "TEST SCRIPT: $*" echo "SHOW ENV VARIABLES: .." env | grep MyTEST env | grep UNISET_TESTSUITE echo "TEST_SCRIPT_RESULT: -20" 



その結果、我々はパラメヌタを含む画像が衚瀺されたす私たちのスクリプトを実行した堎合show_output =«1»をテストでのスクリプトやパラメヌタignore_failed =«1»の䞀぀では
実行するコマンド
 uniset2-testsuite-xmlplayer --testfile tests-scripts-interface.xml --log-show-actions --log-show-tests 




しかし、それだけではありたせん。これたで、1぀の関数のみを実装したしたget_value(...)。あずいく぀か残っおいたす。

支揎掻動はどうですか぀たりset_value関数の実装...
私たちのむンタヌフェヌスでは、サポヌトを行う意味がないず刀断したした
 <action set="..."/> 
定期的なメカニズムがあるため
 <action script=".."/> 

したがっお、関数は次のようになりたす。
set_value..
  def set_value(self, name, value, context): raise TestSuiteException("(scripts:set_value): Function 'set' is not supported. Use <action script='..'> for %s" % name) 



さらに進んでください...
testsuiteには--check-scenarioモヌドがありたす。このモヌドでは、実際に実行するこずなく、蚭定ずテストの正確性がチェックされたす。このモヌドをサポヌトするには、validate_parameterずvalidate_configurationの 2぀の関数を実装する必芁がありたす。max_output_readを陀き、グロヌバル構成パラメヌタヌがないため、構成をチェックむンするための特別なものはありたせん。したがっお、validate_configuration関数は䜕もしたせん。しかしvalidate_parameterもう少し面癜いです。実際、スクリプトによるず、実際に実行せずに怜蚌できる最倧倀は次のずおりです。

これはすべお実装に反映されたす。
validate_parameterおよびvalidate_configurationの実装
  def validate_configuration(self, context): return [True, ""] def validate_parameter(self, name, context): """ :param name: scriptname :param context: ... :return: [Result, errors] """ err = [] xmlnode = None if 'xmlnode' in context: xmlnode = context['xmlnode'] scriptname, params = self.parse_name(name, context) if not scriptname: err.append("(scripts:validate): ERROR: Unknown scriptname for %s" % str(xmlnode)) if not is_executable(scriptname): err.append("(scripts:validate): ERROR: '%s' not exist" % scriptname) if len(err) > 0: return [False, ', '.join(err)] return [True, ""] 


゚ラヌ出力の䟋ずしお、スクリプトに「存圚しない」スクリプトぞの呌び出しを挿入したした。
調敎されたシナリオ
 <?xml version="1.0" encoding="utf-8"?> <TestScenario> <Config> <environment> <item name="MyTEST_VAR1" value="MyTEST_VALUE1"/> <item name="MyTEST_VAR2" value="MyTEST_VALUE2"/> <item name="MyTEST_VAR3" value="MyTEST_VALUE3"/> </environment> <aliases> <item type="scripts" alias="s" default="1"/> </aliases> </Config> <TestList type="scripts"> <test name="Test run script" ignore_failed="1"> <check test="./test-script.sh != 10" params="--param1 3 --param2"/> <check test="./test-script.sh = 100" params="param1=3,param2=4"/> <check test="./test-script-negative-number.sh = -20" show_output="1"/> <check test="./test-script-longtime.sh = 100" timeout="3000"/> <check test="./test-script-error.sh > 10"/> <check test="./non-existent-script.sh > 10"/> </test> </TestList> </TestScenario> 


たた、スクリプトチェックを実行するず、次のようになりたす
実行するコマンド
 uniset2-testsuite-xmlplayer --testfile tests-scripts-interface.xml --log-show-actions --log-show-tests --check-scenario 




さお、これですべおを远加し、むンタヌフェむスの実装の最終バヌゞョンを確認できたす。
UTestInterfaceScripts.py
 #!/usr/bin/env python # -*- coding: utf-8 -*- import os import sys import re import subprocess from UTestInterface import * import uniset2.UGlobal as uglobal class UTestInterfaceScripts(UTestInterface): """      .  : <check test="testscript=VALUE" params="param1 param2 param3.." show_output="1".../> :         (stdout)  TEST_SCRIPT_RESULT: VALUE :    !=0    !         0.  : show_output=1 -    stdout..    ( <Config>): max_output_read="value" -        ,   .  : 1000 """ def __init__(self, **kwargs): """ :param kwargs:  """ UTestInterface.__init__(self, 'scripts', **kwargs) self.max_read = 1000 if 'xmlConfNode' in kwargs: xmlConfNode = kwargs['xmlConfNode'] if not xmlConfNode: raise TestSuiteValidateError("(scripts:init): Unknown confnode") m_read = uglobal.to_int(xmlConfNode.prop("max_output_read")) if m_read > 0: self.max_read = m_read self.re_result = re.compile(r'TEST_SCRIPT_RESULT: ([-]{0,}\d{1,})') @staticmethod def parse_name(name, context): """   : <check test="scriptname=XXX" params="param1 param2 param3" .../> :param name:   (     scriptname) :param context: :return: [scriptname, parameters] """ if 'xmlnode' in context: xmlnode = context['xmlnode'] return [name, uglobal.to_str(xmlnode.prop("params"))] return [name, ""] def validate_configuration(self, context): return [True, ""] def validate_parameter(self, name, context): """ :param name: scriptname :param context: ... :return: [Result, errors] """ err = [] xmlnode = None if 'xmlnode' in context: xmlnode = context['xmlnode'] scriptname, params = self.parse_name(name, context) if not scriptname: err.append("(scripts:validate): ERROR: Unknown scriptname for %s" % str(xmlnode)) if not is_executable(scriptname): err.append("(scripts:validate): ERROR: '%s' not exist" % scriptname) if len(err) > 0: return [False, ', '.join(err)] return [True, ""] def get_value(self, name, context): xmlnode = None if 'xmlnode' in context: xmlnode = context['xmlnode'] if not xmlnode: raise TestSuiteException("(scripts:get_value): Unknown xmlnode for '%s'" % name) scriptname, params = self.parse_name(name, context) if len(scriptname) == 0: raise TestSuiteException("(scripts:get_value): Unknown script name for '%s'" % name) test_env = None if 'environment' in context: test_env = context['environment'] s_out = '' s_err = '' cmd = scriptname + " " + params try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=test_env, close_fds=True, shell=True) s_out = p.stdout.read(self.max_read) s_err = p.stderr.read(self.max_read) retcode = p.wait() if retcode != 0: emessage = "SCRIPT RETCODE(%d) != 0. stderr: %s" % (retcode, s_err.replace("\n", " ")) raise TestSuiteException("(scripts:get_value): %s" % emessage) except subprocess.CalledProcessError, e: raise TestSuiteException("(scripts:get_value): %s for %s" % (e.message, name)) if xmlnode.prop("show_output"): print s_out ret = self.re_result.findall(s_out) if not ret or len(ret) == 0: return None lst = ret[0] if not lst or len(lst) < 1: return None return uglobal.to_int(lst) def set_value(self, name, value, context): raise TestSuiteException( "(scripts:set_value): Function 'set' is not supported. Use <action script='..'> for %s" % name) def uts_create_from_args(**kwargs): """   :param kwargs:   :return:   UTestInterface """ return UTestInterfaceScripts(**kwargs) def uts_create_from_xml(xmlConfNode): """   :param xmlConfNode: xml-   :return:   UTestInterface """ return UTestInterfaceScripts(xmlConfNode=xmlConfNode) def uts_plugin_name(): return "scripts" 



たずめ


uniset2-testsuiteは単玔な自転車で、ほずんどの堎合、テストが「適甚、反応を確認」ずいうスキヌムに適合しおいれば十分です。テスト甚のメカニズムの最小セットが存圚したす。

さらに、プラグむンシステムの存圚により、必芁に応じお機胜を簡単に拡匵し、䜿甚可胜なプロトコルREST APIたたはRS485を䜿甚しおテストシステムずの察話むンタヌフェむスを実装できたす。いく぀かの機胜を実装するだけです。
小さな远加
- python . C++. , python - . .


関連リンク

Source: https://habr.com/ru/post/J323444/


All Articles