pytest-dsl 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. pytest_dsl/core/__init__.py +7 -0
  2. pytest_dsl/core/auth_provider.py +50 -10
  3. pytest_dsl/core/custom_keyword_manager.py +213 -0
  4. pytest_dsl/core/dsl_executor.py +39 -2
  5. pytest_dsl/core/http_client.py +11 -6
  6. pytest_dsl/core/http_request.py +517 -119
  7. pytest_dsl/core/lexer.py +14 -1
  8. pytest_dsl/core/parser.py +45 -2
  9. pytest_dsl/core/parsetab.py +50 -38
  10. pytest_dsl/core/variable_utils.py +1 -1
  11. pytest_dsl/examples/custom/test_advanced_keywords.auto +31 -0
  12. pytest_dsl/examples/custom/test_custom_keywords.auto +37 -0
  13. pytest_dsl/examples/custom/test_default_values.auto +34 -0
  14. pytest_dsl/examples/http/http_retry_assertions.auto +2 -2
  15. pytest_dsl/examples/http/http_retry_assertions_enhanced.auto +2 -2
  16. pytest_dsl/examples/quickstart/api_basics.auto +55 -0
  17. pytest_dsl/examples/quickstart/assertions.auto +31 -0
  18. pytest_dsl/examples/quickstart/loops.auto +24 -0
  19. pytest_dsl/examples/test_custom_keyword.py +9 -0
  20. pytest_dsl/examples/test_http.py +0 -139
  21. pytest_dsl/examples/test_quickstart.py +14 -0
  22. pytest_dsl/keywords/http_keywords.py +290 -102
  23. pytest_dsl/parsetab.py +69 -0
  24. pytest_dsl-0.2.0.dist-info/METADATA +504 -0
  25. {pytest_dsl-0.1.0.dist-info → pytest_dsl-0.2.0.dist-info}/RECORD +29 -24
  26. {pytest_dsl-0.1.0.dist-info → pytest_dsl-0.2.0.dist-info}/WHEEL +1 -1
  27. pytest_dsl/core/custom_auth_example.py +0 -425
  28. pytest_dsl/examples/http/csrf_auth_test.auto +0 -64
  29. pytest_dsl/examples/http/custom_auth_test.auto +0 -76
  30. pytest_dsl/examples/http_clients.yaml +0 -48
  31. pytest_dsl/examples/keyword_example.py +0 -70
  32. pytest_dsl-0.1.0.dist-info/METADATA +0 -537
  33. {pytest_dsl-0.1.0.dist-info → pytest_dsl-0.2.0.dist-info}/entry_points.txt +0 -0
  34. {pytest_dsl-0.1.0.dist-info → pytest_dsl-0.2.0.dist-info}/licenses/LICENSE +0 -0
  35. {pytest_dsl-0.1.0.dist-info → pytest_dsl-0.2.0.dist-info}/top_level.txt +0 -0
pytest_dsl/core/lexer.py CHANGED
@@ -9,7 +9,8 @@ reserved = {
9
9
  'range': 'RANGE',
10
10
  'using': 'USING', # Add new keyword for data-driven testing
11
11
  'True': 'TRUE', # 添加布尔值支持
12
- 'False': 'FALSE' # 添加布尔值支持
12
+ 'False': 'FALSE', # 添加布尔值支持
13
+ 'return': 'RETURN' # 添加return关键字支持
13
14
  }
14
15
 
15
16
  # token 名称列表
@@ -33,6 +34,8 @@ tokens = [
33
34
  'DATE_KEYWORD',
34
35
  'TEARDOWN_KEYWORD',
35
36
  'DATA_KEYWORD', # Add new token for @data keyword
37
+ 'KEYWORD_KEYWORD', # 添加@keyword关键字
38
+ 'IMPORT_KEYWORD', # 添加@import关键字
36
39
  ] + list(reserved.values())
37
40
 
38
41
  # 正则表达式定义 token
@@ -106,6 +109,16 @@ def t_DATA_KEYWORD(t):
106
109
  return t
107
110
 
108
111
 
112
+ def t_KEYWORD_KEYWORD(t):
113
+ r'@keyword'
114
+ return t
115
+
116
+
117
+ def t_IMPORT_KEYWORD(t):
118
+ r'@import'
119
+ return t
120
+
121
+
109
122
  def t_NUMBER(t):
110
123
  r'\d+'
111
124
  t.value = int(t.value)
pytest_dsl/core/parser.py CHANGED
@@ -46,13 +46,16 @@ def p_metadata_item(p):
46
46
  | TAGS_KEYWORD COLON LBRACKET tags RBRACKET
47
47
  | AUTHOR_KEYWORD COLON metadata_value
48
48
  | DATE_KEYWORD COLON DATE
49
- | DATA_KEYWORD COLON data_source'''
49
+ | DATA_KEYWORD COLON data_source
50
+ | IMPORT_KEYWORD COLON STRING'''
50
51
  if p[1] == '@tags':
51
52
  p[0] = Node(p[1], value=p[4])
52
53
  elif p[1] == '@data':
53
54
  # 对于数据驱动测试,将数据源信息存储在节点中
54
55
  data_info = p[3] # 这是一个包含 file 和 format 的字典
55
56
  p[0] = Node(p[1], value=data_info, children=None)
57
+ elif p[1] == '@import':
58
+ p[0] = Node(p[1], value=p[3])
56
59
  else:
57
60
  p[0] = Node(p[1], value=p[3])
58
61
 
@@ -90,7 +93,9 @@ def p_statements(p):
90
93
  def p_statement(p):
91
94
  '''statement : assignment
92
95
  | keyword_call
93
- | loop'''
96
+ | loop
97
+ | custom_keyword
98
+ | return_statement'''
94
99
  p[0] = p[1]
95
100
 
96
101
 
@@ -185,6 +190,44 @@ def p_data_source(p):
185
190
  p[0] = {'file': p[1], 'format': p[3]}
186
191
 
187
192
 
193
+ def p_custom_keyword(p):
194
+ '''custom_keyword : KEYWORD_KEYWORD ID LPAREN param_definitions RPAREN DO statements END'''
195
+ p[0] = Node('CustomKeyword', [p[4], p[7]], p[2])
196
+
197
+
198
+ def p_param_definitions(p):
199
+ '''param_definitions : param_def_list
200
+ | '''
201
+ if len(p) == 2:
202
+ p[0] = p[1]
203
+ else:
204
+ p[0] = []
205
+
206
+
207
+ def p_param_def_list(p):
208
+ '''param_def_list : param_def COMMA param_def_list
209
+ | param_def'''
210
+ if len(p) == 4:
211
+ p[0] = [p[1]] + p[3]
212
+ else:
213
+ p[0] = [p[1]]
214
+
215
+
216
+ def p_param_def(p):
217
+ '''param_def : ID EQUALS STRING
218
+ | ID EQUALS NUMBER
219
+ | ID'''
220
+ if len(p) == 4:
221
+ p[0] = Node('ParameterDef', [Node('Expression', value=p[3])], p[1])
222
+ else:
223
+ p[0] = Node('ParameterDef', [], p[1])
224
+
225
+
226
+ def p_return_statement(p):
227
+ '''return_statement : RETURN expression'''
228
+ p[0] = Node('Return', [p[2]])
229
+
230
+
188
231
  def p_error(p):
189
232
  if p:
190
233
  print(
@@ -6,9 +6,9 @@ _tabversion = '3.10'
6
6
 
7
7
  _lr_method = 'LALR'
8
8
 
9
- _lr_signature = 'leftCOMMArightEQUALSAUTHOR_KEYWORD COLON COMMA DATA_KEYWORD DATE DATE_KEYWORD DESCRIPTION_KEYWORD DO END EQUALS FALSE FOR ID IN LBRACKET LPAREN NAME_KEYWORD NUMBER PLACEHOLDER RANGE RBRACKET RPAREN STRING TAGS_KEYWORD TEARDOWN_KEYWORD TRUE USINGstart : metadata statements teardown\n | metadata statementsmetadata : metadata_itemsmetadata_items : metadata_item metadata_items\n | metadata_itemmetadata_item : NAME_KEYWORD COLON metadata_value\n | DESCRIPTION_KEYWORD COLON metadata_value\n | TAGS_KEYWORD COLON LBRACKET tags RBRACKET\n | AUTHOR_KEYWORD COLON metadata_value\n | DATE_KEYWORD COLON DATE\n | DATA_KEYWORD COLON data_sourcemetadata_value : STRING\n | IDtags : tag COMMA tags\n | tagtag : STRING\n | IDstatements : statement statements\n | statementstatement : assignment\n | keyword_call\n | loopassignment : ID EQUALS expression\n | ID EQUALS keyword_callexpression : NUMBER\n | STRING\n | PLACEHOLDER\n | ID\n | boolean_expr\n | list_exprboolean_expr : TRUE\n | FALSElist_expr : LBRACKET list_items RBRACKET\n | LBRACKET RBRACKETlist_items : list_item\n | list_item COMMA list_itemslist_item : expressionloop : FOR ID IN RANGE LPAREN expression COMMA expression RPAREN DO statements ENDkeyword_call : LBRACKET ID RBRACKET COMMA parameter_list\n | LBRACKET ID RBRACKETparameter_list : parameter_itemsparameter_items : parameter_item COMMA parameter_items\n | parameter_itemparameter_item : ID COLON expressionteardown : TEARDOWN_KEYWORD DO statements ENDdata_source : STRING USING ID'
9
+ _lr_signature = 'leftCOMMArightEQUALSAUTHOR_KEYWORD COLON COMMA DATA_KEYWORD DATE DATE_KEYWORD DESCRIPTION_KEYWORD DO END EQUALS FALSE FOR ID IMPORT_KEYWORD IN KEYWORD_KEYWORD LBRACKET LPAREN NAME_KEYWORD NUMBER PLACEHOLDER RANGE RBRACKET RETURN RPAREN STRING TAGS_KEYWORD TEARDOWN_KEYWORD TRUE USINGstart : metadata statements teardown\n | metadata statementsmetadata : metadata_itemsmetadata_items : metadata_item metadata_items\n | metadata_itemmetadata_item : NAME_KEYWORD COLON metadata_value\n | DESCRIPTION_KEYWORD COLON metadata_value\n | TAGS_KEYWORD COLON LBRACKET tags RBRACKET\n | AUTHOR_KEYWORD COLON metadata_value\n | DATE_KEYWORD COLON DATE\n | DATA_KEYWORD COLON data_source\n | IMPORT_KEYWORD COLON STRINGmetadata_value : STRING\n | IDtags : tag COMMA tags\n | tagtag : STRING\n | IDstatements : statement statements\n | statementstatement : assignment\n | keyword_call\n | loop\n | custom_keyword\n | return_statementassignment : ID EQUALS expression\n | ID EQUALS keyword_callexpression : NUMBER\n | STRING\n | PLACEHOLDER\n | ID\n | boolean_expr\n | list_exprboolean_expr : TRUE\n | FALSElist_expr : LBRACKET list_items RBRACKET\n | LBRACKET RBRACKETlist_items : list_item\n | list_item COMMA list_itemslist_item : expressionloop : FOR ID IN RANGE LPAREN expression COMMA expression RPAREN DO statements ENDkeyword_call : LBRACKET ID RBRACKET COMMA parameter_list\n | LBRACKET ID RBRACKETparameter_list : parameter_itemsparameter_items : parameter_item COMMA parameter_items\n | parameter_itemparameter_item : ID COLON expressionteardown : TEARDOWN_KEYWORD DO statements ENDdata_source : STRING USING IDcustom_keyword : KEYWORD_KEYWORD ID LPAREN param_definitions RPAREN DO statements ENDparam_definitions : param_def_list\n | param_def_list : param_def COMMA param_def_list\n | param_defparam_def : ID EQUALS STRING\n | ID EQUALS NUMBER\n | IDreturn_statement : RETURN expression'
10
10
 
11
- _lr_action_items = {'NAME_KEYWORD':([0,4,32,33,34,35,37,38,39,69,71,],[5,5,-6,-12,-13,-7,-9,-10,-11,-8,-46,]),'DESCRIPTION_KEYWORD':([0,4,32,33,34,35,37,38,39,69,71,],[6,6,-6,-12,-13,-7,-9,-10,-11,-8,-46,]),'TAGS_KEYWORD':([0,4,32,33,34,35,37,38,39,69,71,],[7,7,-6,-12,-13,-7,-9,-10,-11,-8,-46,]),'AUTHOR_KEYWORD':([0,4,32,33,34,35,37,38,39,69,71,],[8,8,-6,-12,-13,-7,-9,-10,-11,-8,-46,]),'DATE_KEYWORD':([0,4,32,33,34,35,37,38,39,69,71,],[9,9,-6,-12,-13,-7,-9,-10,-11,-8,-46,]),'DATA_KEYWORD':([0,4,32,33,34,35,37,38,39,69,71,],[10,10,-6,-12,-13,-7,-9,-10,-11,-8,-46,]),'$end':([1,11,12,13,14,15,26,28,42,43,44,45,46,47,48,49,51,52,53,63,72,73,76,77,78,85,86,92,],[0,-2,-19,-20,-21,-22,-1,-18,-28,-23,-24,-25,-26,-27,-29,-30,-31,-32,-40,-34,-45,-33,-39,-41,-43,-44,-42,-38,]),'ID':([2,3,4,12,13,14,15,17,18,19,20,21,23,29,32,33,34,35,36,37,38,39,41,42,43,44,45,46,47,48,49,50,51,52,53,59,61,63,67,69,70,71,73,74,76,77,78,79,82,83,85,86,87,90,92,],[16,-3,-5,16,-20,-21,-22,30,31,-4,34,34,34,42,-6,-12,-13,-7,58,-9,-10,-11,16,-28,-23,-24,-25,-26,-27,-29,-30,62,-31,-32,-40,71,42,-34,75,-8,58,-46,-33,42,-39,-41,-43,42,42,75,-44,-42,42,16,-38,]),'LBRACKET':([2,3,4,12,13,14,15,19,22,29,32,33,34,35,37,38,39,41,42,43,44,45,46,47,48,49,50,51,52,53,61,63,69,71,73,74,76,77,78,79,82,85,86,87,90,92,],[17,-3,-5,17,-20,-21,-22,-4,36,50,-6,-12,-13,-7,-9,-10,-11,17,-28,-23,-24,-25,-26,-27,-29,-30,61,-31,-32,-40,61,-34,-8,-46,-33,61,-39,-41,-43,61,61,-44,-42,61,17,-38,]),'FOR':([2,3,4,12,13,14,15,19,32,33,34,35,37,38,39,41,42,43,44,45,46,47,48,49,51,52,53,63,69,71,73,76,77,78,85,86,90,92,],[18,-3,-5,18,-20,-21,-22,-4,-6,-12,-13,-7,-9,-10,-11,18,-28,-23,-24,-25,-26,-27,-29,-30,-31,-32,-40,-34,-8,-46,-33,-39,-41,-43,-44,-42,18,-38,]),'COLON':([5,6,7,8,9,10,75,],[20,21,22,23,24,25,82,]),'TEARDOWN_KEYWORD':([11,12,13,14,15,28,42,43,44,45,46,47,48,49,51,52,53,63,73,76,77,78,85,86,92,],[27,-19,-20,-21,-22,-18,-28,-23,-24,-25,-26,-27,-29,-30,-31,-32,-40,-34,-33,-39,-41,-43,-44,-42,-38,]),'END':([12,13,14,15,28,42,43,44,45,46,47,48,49,51,52,53,60,63,73,76,77,78,85,86,91,92,],[-19,-20,-21,-22,-18,-28,-23,-24,-25,-26,-27,-29,-30,-31,-32,-40,72,-34,-33,-39,-41,-43,-44,-42,92,-38,]),'EQUALS':([16,],[29,]),'STRING':([20,21,23,25,29,36,50,61,70,74,79,82,87,],[33,33,33,40,46,57,46,46,57,46,46,46,46,]),'DATE':([24,],[38,]),'DO':([27,89,],[41,90,]),'NUMBER':([29,50,61,74,79,82,87,],[45,45,45,45,45,45,45,]),'PLACEHOLDER':([29,50,61,74,79,82,87,],[47,47,47,47,47,47,47,]),'TRUE':([29,50,61,74,79,82,87,],[51,51,51,51,51,51,51,]),'FALSE':([29,50,61,74,79,82,87,],[52,52,52,52,52,52,52,]),'RBRACKET':([30,42,45,46,47,48,49,50,51,52,55,56,57,58,61,62,63,64,65,66,73,80,81,],[53,-28,-25,-26,-27,-29,-30,63,-31,-32,69,-15,-16,-17,63,53,-34,73,-35,-37,-33,-14,-36,]),'IN':([31,],[54,]),'USING':([40,],[59,]),'COMMA':([42,45,46,47,48,49,51,52,53,56,57,58,62,63,65,66,73,78,84,85,],[-28,-25,-26,-27,-29,-30,-31,-32,67,70,-16,-17,-28,-34,74,-37,-33,83,87,-44,]),'RPAREN':([42,45,46,47,48,49,51,52,63,73,88,],[-28,-25,-26,-27,-29,-30,-31,-32,-34,-33,89,]),'RANGE':([54,],[68,]),'LPAREN':([68,],[79,]),}
11
+ _lr_action_items = {'NAME_KEYWORD':([0,4,49,50,51,52,54,55,56,58,85,87,],[5,5,-6,-13,-14,-7,-9,-10,-11,-12,-8,-49,]),'DESCRIPTION_KEYWORD':([0,4,49,50,51,52,54,55,56,58,85,87,],[6,6,-6,-13,-14,-7,-9,-10,-11,-12,-8,-49,]),'TAGS_KEYWORD':([0,4,49,50,51,52,54,55,56,58,85,87,],[7,7,-6,-13,-14,-7,-9,-10,-11,-12,-8,-49,]),'AUTHOR_KEYWORD':([0,4,49,50,51,52,54,55,56,58,85,87,],[8,8,-6,-13,-14,-7,-9,-10,-11,-12,-8,-49,]),'DATE_KEYWORD':([0,4,49,50,51,52,54,55,56,58,85,87,],[9,9,-6,-13,-14,-7,-9,-10,-11,-12,-8,-49,]),'DATA_KEYWORD':([0,4,49,50,51,52,54,55,56,58,85,87,],[10,10,-6,-13,-14,-7,-9,-10,-11,-12,-8,-49,]),'IMPORT_KEYWORD':([0,4,49,50,51,52,54,55,56,58,85,87,],[11,11,-6,-13,-14,-7,-9,-10,-11,-12,-8,-49,]),'$end':([1,12,13,14,15,16,17,18,32,34,39,40,41,42,43,44,45,46,47,60,61,63,67,83,88,90,91,92,106,107,111,115,],[0,-2,-20,-21,-22,-23,-24,-25,-1,-19,-58,-28,-29,-30,-31,-32,-33,-34,-35,-26,-27,-43,-37,-36,-48,-42,-44,-46,-47,-45,-50,-41,]),'ID':([2,3,4,13,14,15,16,17,18,20,21,22,23,24,25,26,28,35,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,58,59,60,61,62,63,65,67,74,77,83,84,85,86,87,90,91,92,93,96,99,100,104,106,107,108,111,113,115,],[19,-3,-5,19,-21,-22,-23,-24,-25,36,37,38,43,-4,51,51,51,43,-58,-28,-29,-30,-31,-32,-33,-34,-35,43,-6,-13,-14,-7,73,-9,-10,-11,-12,19,-26,-27,76,-43,79,-37,87,89,-36,43,-8,73,-49,-42,-44,-46,43,79,43,89,19,-47,-45,43,-50,19,-41,]),'LBRACKET':([2,3,4,13,14,15,16,17,18,23,24,27,35,39,40,41,42,43,44,45,46,47,48,49,50,51,52,54,55,56,58,59,60,61,62,63,67,83,84,85,87,90,91,92,93,99,104,106,107,108,111,113,115,],[20,-3,-5,20,-21,-22,-23,-24,-25,48,-4,53,62,-58,-28,-29,-30,-31,-32,-33,-34,-35,48,-6,-13,-14,-7,-9,-10,-11,-12,20,-26,-27,48,-43,-37,-36,48,-8,-49,-42,-44,-46,48,48,20,-47,-45,48,-50,20,-41,]),'FOR':([2,3,4,13,14,15,16,17,18,24,39,40,41,42,43,44,45,46,47,49,50,51,52,54,55,56,58,59,60,61,63,67,83,85,87,90,91,92,104,106,107,111,113,115,],[21,-3,-5,21,-21,-22,-23,-24,-25,-4,-58,-28,-29,-30,-31,-32,-33,-34,-35,-6,-13,-14,-7,-9,-10,-11,-12,21,-26,-27,-43,-37,-36,-8,-49,-42,-44,-46,21,-47,-45,-50,21,-41,]),'KEYWORD_KEYWORD':([2,3,4,13,14,15,16,17,18,24,39,40,41,42,43,44,45,46,47,49,50,51,52,54,55,56,58,59,60,61,63,67,83,85,87,90,91,92,104,106,107,111,113,115,],[22,-3,-5,22,-21,-22,-23,-24,-25,-4,-58,-28,-29,-30,-31,-32,-33,-34,-35,-6,-13,-14,-7,-9,-10,-11,-12,22,-26,-27,-43,-37,-36,-8,-49,-42,-44,-46,22,-47,-45,-50,22,-41,]),'RETURN':([2,3,4,13,14,15,16,17,18,24,39,40,41,42,43,44,45,46,47,49,50,51,52,54,55,56,58,59,60,61,63,67,83,85,87,90,91,92,104,106,107,111,113,115,],[23,-3,-5,23,-21,-22,-23,-24,-25,-4,-58,-28,-29,-30,-31,-32,-33,-34,-35,-6,-13,-14,-7,-9,-10,-11,-12,23,-26,-27,-43,-37,-36,-8,-49,-42,-44,-46,23,-47,-45,-50,23,-41,]),'COLON':([5,6,7,8,9,10,11,89,],[25,26,27,28,29,30,31,99,]),'TEARDOWN_KEYWORD':([12,13,14,15,16,17,18,34,39,40,41,42,43,44,45,46,47,60,61,63,67,83,90,91,92,106,107,111,115,],[33,-20,-21,-22,-23,-24,-25,-19,-58,-28,-29,-30,-31,-32,-33,-34,-35,-26,-27,-43,-37,-36,-42,-44,-46,-47,-45,-50,-41,]),'END':([13,14,15,16,17,18,34,39,40,41,42,43,44,45,46,47,60,61,63,67,75,83,90,91,92,106,107,109,111,114,115,],[-20,-21,-22,-23,-24,-25,-19,-58,-28,-29,-30,-31,-32,-33,-34,-35,-26,-27,-43,-37,88,-36,-42,-44,-46,-47,-45,111,-50,115,-41,]),'EQUALS':([19,79,],[35,94,]),'NUMBER':([23,35,48,62,84,93,94,99,108,],[40,40,40,40,40,40,103,40,40,]),'STRING':([23,25,26,28,30,31,35,48,53,62,84,86,93,94,99,108,],[41,50,50,50,57,58,41,41,72,41,41,72,41,102,41,41,]),'PLACEHOLDER':([23,35,48,62,84,93,99,108,],[42,42,42,42,42,42,42,42,]),'TRUE':([23,35,48,62,84,93,99,108,],[46,46,46,46,46,46,46,46,]),'FALSE':([23,35,48,62,84,93,99,108,],[47,47,47,47,47,47,47,47,]),'DATE':([29,],[55,]),'DO':([33,95,112,],[59,104,113,]),'RBRACKET':([36,40,41,42,43,44,45,46,47,48,62,66,67,68,69,70,71,72,73,76,83,97,98,],[63,-28,-29,-30,-31,-32,-33,-34,-35,67,67,83,-37,-38,-40,85,-16,-17,-18,63,-36,-39,-15,]),'IN':([37,],[64,]),'LPAREN':([38,78,],[65,93,]),'COMMA':([40,41,42,43,44,45,46,47,63,67,68,69,71,72,73,76,79,82,83,92,101,102,103,106,],[-28,-29,-30,-31,-32,-33,-34,-35,77,-37,84,-40,86,-17,-18,-31,-57,96,-36,100,108,-55,-56,-47,]),'RPAREN':([40,41,42,43,44,45,46,47,65,67,79,80,81,82,83,102,103,105,110,],[-28,-29,-30,-31,-32,-33,-34,-35,-52,-37,-57,95,-51,-54,-36,-55,-56,-53,112,]),'USING':([57,],[74,]),'RANGE':([64,],[78,]),}
12
12
 
13
13
  _lr_action = {}
14
14
  for _k, _v in _lr_action_items.items():
@@ -17,7 +17,7 @@ for _k, _v in _lr_action_items.items():
17
17
  _lr_action[_x][_k] = _y
18
18
  del _lr_action_items
19
19
 
20
- _lr_goto_items = {'start':([0,],[1,]),'metadata':([0,],[2,]),'metadata_items':([0,4,],[3,19,]),'metadata_item':([0,4,],[4,4,]),'statements':([2,12,41,90,],[11,28,60,91,]),'statement':([2,12,41,90,],[12,12,12,12,]),'assignment':([2,12,41,90,],[13,13,13,13,]),'keyword_call':([2,12,29,41,90,],[14,14,44,14,14,]),'loop':([2,12,41,90,],[15,15,15,15,]),'teardown':([11,],[26,]),'metadata_value':([20,21,23,],[32,35,37,]),'data_source':([25,],[39,]),'expression':([29,50,61,74,79,82,87,],[43,66,66,66,84,85,88,]),'boolean_expr':([29,50,61,74,79,82,87,],[48,48,48,48,48,48,48,]),'list_expr':([29,50,61,74,79,82,87,],[49,49,49,49,49,49,49,]),'tags':([36,70,],[55,80,]),'tag':([36,70,],[56,56,]),'list_items':([50,61,74,],[64,64,81,]),'list_item':([50,61,74,],[65,65,65,]),'parameter_list':([67,],[76,]),'parameter_items':([67,83,],[77,86,]),'parameter_item':([67,83,],[78,78,]),}
20
+ _lr_goto_items = {'start':([0,],[1,]),'metadata':([0,],[2,]),'metadata_items':([0,4,],[3,24,]),'metadata_item':([0,4,],[4,4,]),'statements':([2,13,59,104,113,],[12,34,75,109,114,]),'statement':([2,13,59,104,113,],[13,13,13,13,13,]),'assignment':([2,13,59,104,113,],[14,14,14,14,14,]),'keyword_call':([2,13,35,59,104,113,],[15,15,61,15,15,15,]),'loop':([2,13,59,104,113,],[16,16,16,16,16,]),'custom_keyword':([2,13,59,104,113,],[17,17,17,17,17,]),'return_statement':([2,13,59,104,113,],[18,18,18,18,18,]),'teardown':([12,],[32,]),'expression':([23,35,48,62,84,93,99,108,],[39,60,69,69,69,101,106,110,]),'boolean_expr':([23,35,48,62,84,93,99,108,],[44,44,44,44,44,44,44,44,]),'list_expr':([23,35,48,62,84,93,99,108,],[45,45,45,45,45,45,45,45,]),'metadata_value':([25,26,28,],[49,52,54,]),'data_source':([30,],[56,]),'list_items':([48,62,84,],[66,66,97,]),'list_item':([48,62,84,],[68,68,68,]),'tags':([53,86,],[70,98,]),'tag':([53,86,],[71,71,]),'param_definitions':([65,],[80,]),'param_def_list':([65,96,],[81,105,]),'param_def':([65,96,],[82,82,]),'parameter_list':([77,],[90,]),'parameter_items':([77,100,],[91,107,]),'parameter_item':([77,100,],[92,92,]),}
21
21
 
22
22
  _lr_goto = {}
23
23
  for _k, _v in _lr_goto_items.items():
@@ -38,39 +38,51 @@ _lr_productions = [
38
38
  ('metadata_item -> AUTHOR_KEYWORD COLON metadata_value','metadata_item',3,'p_metadata_item','parser.py',47),
39
39
  ('metadata_item -> DATE_KEYWORD COLON DATE','metadata_item',3,'p_metadata_item','parser.py',48),
40
40
  ('metadata_item -> DATA_KEYWORD COLON data_source','metadata_item',3,'p_metadata_item','parser.py',49),
41
- ('metadata_value -> STRING','metadata_value',1,'p_metadata_value','parser.py',61),
42
- ('metadata_value -> ID','metadata_value',1,'p_metadata_value','parser.py',62),
43
- ('tags -> tag COMMA tags','tags',3,'p_tags','parser.py',67),
44
- ('tags -> tag','tags',1,'p_tags','parser.py',68),
45
- ('tag -> STRING','tag',1,'p_tag','parser.py',76),
46
- ('tag -> ID','tag',1,'p_tag','parser.py',77),
47
- ('statements -> statement statements','statements',2,'p_statements','parser.py',82),
48
- ('statements -> statement','statements',1,'p_statements','parser.py',83),
49
- ('statement -> assignment','statement',1,'p_statement','parser.py',91),
50
- ('statement -> keyword_call','statement',1,'p_statement','parser.py',92),
51
- ('statement -> loop','statement',1,'p_statement','parser.py',93),
52
- ('assignment -> ID EQUALS expression','assignment',3,'p_assignment','parser.py',98),
53
- ('assignment -> ID EQUALS keyword_call','assignment',3,'p_assignment','parser.py',99),
54
- ('expression -> NUMBER','expression',1,'p_expression','parser.py',107),
55
- ('expression -> STRING','expression',1,'p_expression','parser.py',108),
56
- ('expression -> PLACEHOLDER','expression',1,'p_expression','parser.py',109),
57
- ('expression -> ID','expression',1,'p_expression','parser.py',110),
58
- ('expression -> boolean_expr','expression',1,'p_expression','parser.py',111),
59
- ('expression -> list_expr','expression',1,'p_expression','parser.py',112),
60
- ('boolean_expr -> TRUE','boolean_expr',1,'p_boolean_expr','parser.py',117),
61
- ('boolean_expr -> FALSE','boolean_expr',1,'p_boolean_expr','parser.py',118),
62
- ('list_expr -> LBRACKET list_items RBRACKET','list_expr',3,'p_list_expr','parser.py',123),
63
- ('list_expr -> LBRACKET RBRACKET','list_expr',2,'p_list_expr','parser.py',124),
64
- ('list_items -> list_item','list_items',1,'p_list_items','parser.py',132),
65
- ('list_items -> list_item COMMA list_items','list_items',3,'p_list_items','parser.py',133),
66
- ('list_item -> expression','list_item',1,'p_list_item','parser.py',141),
67
- ('loop -> FOR ID IN RANGE LPAREN expression COMMA expression RPAREN DO statements END','loop',12,'p_loop','parser.py',146),
68
- ('keyword_call -> LBRACKET ID RBRACKET COMMA parameter_list','keyword_call',5,'p_keyword_call','parser.py',151),
69
- ('keyword_call -> LBRACKET ID RBRACKET','keyword_call',3,'p_keyword_call','parser.py',152),
70
- ('parameter_list -> parameter_items','parameter_list',1,'p_parameter_list','parser.py',160),
71
- ('parameter_items -> parameter_item COMMA parameter_items','parameter_items',3,'p_parameter_items','parser.py',165),
72
- ('parameter_items -> parameter_item','parameter_items',1,'p_parameter_items','parser.py',166),
73
- ('parameter_item -> ID COLON expression','parameter_item',3,'p_parameter_item','parser.py',174),
74
- ('teardown -> TEARDOWN_KEYWORD DO statements END','teardown',4,'p_teardown','parser.py',179),
75
- ('data_source -> STRING USING ID','data_source',3,'p_data_source','parser.py',184),
41
+ ('metadata_item -> IMPORT_KEYWORD COLON STRING','metadata_item',3,'p_metadata_item','parser.py',50),
42
+ ('metadata_value -> STRING','metadata_value',1,'p_metadata_value','parser.py',64),
43
+ ('metadata_value -> ID','metadata_value',1,'p_metadata_value','parser.py',65),
44
+ ('tags -> tag COMMA tags','tags',3,'p_tags','parser.py',70),
45
+ ('tags -> tag','tags',1,'p_tags','parser.py',71),
46
+ ('tag -> STRING','tag',1,'p_tag','parser.py',79),
47
+ ('tag -> ID','tag',1,'p_tag','parser.py',80),
48
+ ('statements -> statement statements','statements',2,'p_statements','parser.py',85),
49
+ ('statements -> statement','statements',1,'p_statements','parser.py',86),
50
+ ('statement -> assignment','statement',1,'p_statement','parser.py',94),
51
+ ('statement -> keyword_call','statement',1,'p_statement','parser.py',95),
52
+ ('statement -> loop','statement',1,'p_statement','parser.py',96),
53
+ ('statement -> custom_keyword','statement',1,'p_statement','parser.py',97),
54
+ ('statement -> return_statement','statement',1,'p_statement','parser.py',98),
55
+ ('assignment -> ID EQUALS expression','assignment',3,'p_assignment','parser.py',103),
56
+ ('assignment -> ID EQUALS keyword_call','assignment',3,'p_assignment','parser.py',104),
57
+ ('expression -> NUMBER','expression',1,'p_expression','parser.py',112),
58
+ ('expression -> STRING','expression',1,'p_expression','parser.py',113),
59
+ ('expression -> PLACEHOLDER','expression',1,'p_expression','parser.py',114),
60
+ ('expression -> ID','expression',1,'p_expression','parser.py',115),
61
+ ('expression -> boolean_expr','expression',1,'p_expression','parser.py',116),
62
+ ('expression -> list_expr','expression',1,'p_expression','parser.py',117),
63
+ ('boolean_expr -> TRUE','boolean_expr',1,'p_boolean_expr','parser.py',122),
64
+ ('boolean_expr -> FALSE','boolean_expr',1,'p_boolean_expr','parser.py',123),
65
+ ('list_expr -> LBRACKET list_items RBRACKET','list_expr',3,'p_list_expr','parser.py',128),
66
+ ('list_expr -> LBRACKET RBRACKET','list_expr',2,'p_list_expr','parser.py',129),
67
+ ('list_items -> list_item','list_items',1,'p_list_items','parser.py',137),
68
+ ('list_items -> list_item COMMA list_items','list_items',3,'p_list_items','parser.py',138),
69
+ ('list_item -> expression','list_item',1,'p_list_item','parser.py',146),
70
+ ('loop -> FOR ID IN RANGE LPAREN expression COMMA expression RPAREN DO statements END','loop',12,'p_loop','parser.py',151),
71
+ ('keyword_call -> LBRACKET ID RBRACKET COMMA parameter_list','keyword_call',5,'p_keyword_call','parser.py',156),
72
+ ('keyword_call -> LBRACKET ID RBRACKET','keyword_call',3,'p_keyword_call','parser.py',157),
73
+ ('parameter_list -> parameter_items','parameter_list',1,'p_parameter_list','parser.py',165),
74
+ ('parameter_items -> parameter_item COMMA parameter_items','parameter_items',3,'p_parameter_items','parser.py',170),
75
+ ('parameter_items -> parameter_item','parameter_items',1,'p_parameter_items','parser.py',171),
76
+ ('parameter_item -> ID COLON expression','parameter_item',3,'p_parameter_item','parser.py',179),
77
+ ('teardown -> TEARDOWN_KEYWORD DO statements END','teardown',4,'p_teardown','parser.py',184),
78
+ ('data_source -> STRING USING ID','data_source',3,'p_data_source','parser.py',189),
79
+ ('custom_keyword -> KEYWORD_KEYWORD ID LPAREN param_definitions RPAREN DO statements END','custom_keyword',8,'p_custom_keyword','parser.py',194),
80
+ ('param_definitions -> param_def_list','param_definitions',1,'p_param_definitions','parser.py',199),
81
+ ('param_definitions -> <empty>','param_definitions',0,'p_param_definitions','parser.py',200),
82
+ ('param_def_list -> param_def COMMA param_def_list','param_def_list',3,'p_param_def_list','parser.py',208),
83
+ ('param_def_list -> param_def','param_def_list',1,'p_param_def_list','parser.py',209),
84
+ ('param_def -> ID EQUALS STRING','param_def',3,'p_param_def','parser.py',217),
85
+ ('param_def -> ID EQUALS NUMBER','param_def',3,'p_param_def','parser.py',218),
86
+ ('param_def -> ID','param_def',1,'p_param_def','parser.py',219),
87
+ ('return_statement -> RETURN expression','return_statement',2,'p_return_statement','parser.py',227),
76
88
  ]
@@ -110,7 +110,7 @@ class VariableReplacer:
110
110
  return value
111
111
 
112
112
  # 处理变量引用模式: ${variable} 或 ${variable.field.subfield}
113
- pattern = r'\$\{([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)\}'
113
+ pattern = r'\$\{([a-zA-Z_\u4e00-\u9fa5][a-zA-Z0-9_\u4e00-\u9fa5]*(?:\.[a-zA-Z_\u4e00-\u9fa5][a-zA-Z0-9_\u4e00-\u9fa5]*)*)\}'
114
114
 
115
115
  result = value
116
116
  matches = list(re.finditer(pattern, result))
@@ -0,0 +1,31 @@
1
+ @name: 高级自定义关键字测试
2
+ @description: 测试带嵌套导入的自定义关键字功能
3
+ @tags: [测试, 自定义关键字, 嵌套导入]
4
+ @author: Felix
5
+ @date: 2024-06-11
6
+
7
+ # 导入高级工具资源文件(该文件已导入基础工具资源文件)
8
+ @import: "pytest_dsl/examples/custom/resources/advanced_utils.resource"
9
+
10
+ [打印],内容:'开始测试高级自定义关键字'
11
+
12
+ # 测试基础工具中的格式化消息关键字
13
+ 消息模板值 = "当前状态"
14
+ 变量值 = "正在运行"
15
+ 格式化结果 = [格式化消息],消息模板:${消息模板值},变量:${变量值}
16
+ [打印],内容:'基础工具格式化结果: ${格式化结果}'
17
+
18
+ [断言],条件:'${格式化结果} == "当前状态: 正在运行"',消息:'格式化消息结果不匹配'
19
+
20
+ # 测试高级工具中的生成报告消息关键字
21
+ 标题值 = "测试报告"
22
+ 内容值 = "测试全部通过"
23
+ 报告结果 = [生成报告消息],标题:${标题值},内容:${内容值}
24
+ [打印],内容:'生成的报告:\n${报告结果}'
25
+
26
+ # 不进行复杂断言,只确认返回结果不为空
27
+ [断言],条件:'${报告结果} != ""',消息:'报告结果不应为空'
28
+
29
+ @teardown do
30
+ [打印],内容:'高级自定义关键字测试完成'
31
+ end
@@ -0,0 +1,37 @@
1
+ @name: 自定义关键字测试
2
+ @description: 测试自定义关键字功能
3
+ @tags: [测试, 自定义关键字]
4
+ @author: Felix
5
+ @date: 2024-06-11
6
+
7
+ # 导入资源文件
8
+ @import: "pytest_dsl/examples/custom/resources/common_utils.resource"
9
+
10
+ [打印],内容:'开始测试自定义关键字'
11
+
12
+ # 定义测试输入参数
13
+ 前缀值 = "你好, "
14
+ 后缀值 = "世界"
15
+
16
+ # 测试拼接字符串关键字
17
+ [打印],内容:'测试拼接字符串关键字'
18
+ 拼接结果 = [拼接字符串],前缀:${前缀值},后缀:${后缀值}
19
+ [打印],内容:'获取到拼接结果: ${拼接结果}'
20
+
21
+ 拼接结果2 = [拼接字符串],前缀:haha
22
+ [打印],内容:'获取到拼接结果2: ${拼接结果2}'
23
+
24
+ # 测试断言
25
+ [断言],条件:'${拼接结果} == "你好, 世界"',消息:'字符串拼接不匹配'
26
+
27
+ # 测试计算长度关键字
28
+ [打印],内容:'测试计算长度关键字'
29
+ 测试文本 = "这是测试文本"
30
+ 文本长度 = [计算长度],文本:${测试文本}
31
+ [打印],内容:'获取到文本长度: ${文本长度}'
32
+
33
+ [断言],条件:'${文本长度} == 10',消息:'长度不匹配'
34
+
35
+ @teardown do
36
+ [打印],内容:'自定义关键字测试完成'
37
+ end
@@ -0,0 +1,34 @@
1
+ @name: 默认值测试
2
+ @description: 测试自定义关键字默认值功能
3
+ @tags: [测试, 自定义关键字, 默认值]
4
+ @author: Felix
5
+ @date: 2024-06-11
6
+
7
+ # 导入资源文件
8
+ @import: "pytest_dsl/examples/custom/resources/common_utils.resource"
9
+ @import: "pytest_dsl/examples/custom/resources/base_utils.resource"
10
+ @import: "pytest_dsl/examples/custom/resources/advanced_utils.resource"
11
+
12
+ [打印],内容:'开始测试自定义关键字默认值'
13
+
14
+ # 测试带默认值的参数 - 不传递该参数
15
+ [打印],内容:'测试不提供带默认值的参数:'
16
+ 拼接结果1 = [拼接字符串],前缀:"Hello "
17
+ [打印],内容:'使用默认后缀的拼接结果: ${拼接结果1}'
18
+
19
+ # 测试带默认值的参数 - 传递该参数
20
+ [打印],内容:'测试提供带默认值的参数:'
21
+ 拼接结果2 = [拼接字符串],前缀:"Hello ",后缀:"Override"
22
+ [打印],内容:'使用自定义后缀的拼接结果: ${拼接结果2}'
23
+
24
+ # 测试base_utils.resource中的带默认值关键字
25
+ 格式化结果1 = [格式化消息],消息模板:"测试消息"
26
+ [打印],内容:'使用默认变量的格式化结果: ${格式化结果1}'
27
+
28
+ # 测试advanced_utils.resource中的带默认值关键字
29
+ 报告结果1 = [生成报告消息],标题:"仅标题测试"
30
+ [打印],内容:'使用默认内容的报告:\n${报告结果1}'
31
+
32
+ @teardown do
33
+ [打印],内容:'默认值测试完成'
34
+ end
@@ -16,7 +16,7 @@
16
16
  asserts:
17
17
  - ["status", "eq", 200]
18
18
  - ["jsonpath", "$.url", "contains", "httpbin.org"]
19
- - ["response_time", "lt", 1000] # 这个断言可能会失败,因为请求延迟约2秒
19
+ - ["response_time", "lt", 3000] # 这个断言可能会失败,因为请求延迟约2秒
20
20
  ''',步骤名称: "旧版全局断言重试示例"
21
21
 
22
22
  # 示例2: 使用indices指定重试特定断言
@@ -56,7 +56,7 @@
56
56
  url: https://httpbin.org/delay/1
57
57
  asserts:
58
58
  - ["status", "eq", 200] # 索引0
59
- - ["response_time", "lt", 800] # 索引1
59
+ - ["response_time", "lt", 2000] # 索引1
60
60
  - ["jsonpath", "$.headers.Host", "eq", "httpbin.org"] # 索引2
61
61
  - ["jsonpath", "$.url", "contains", "httpbin.org"] # 索引3
62
62
  retry_assertions:
@@ -13,7 +13,7 @@
13
13
  asserts:
14
14
  - ["status", "eq", 200]
15
15
  - ["jsonpath", "$.url", "contains", "httpbin.org"]
16
- - ["response_time", "lt", 1000] # 这个断言可能会失败,因为请求延迟约2秒
16
+ - ["response_time", "lt", 3003] # 这个断言可能会失败,因为请求延迟约2秒
17
17
  retry_assertions:
18
18
  count: 3
19
19
  interval: 1
@@ -57,7 +57,7 @@
57
57
  url: https://httpbin.org/delay/1
58
58
  asserts:
59
59
  - ["status", "eq", 200] # 索引0
60
- - ["response_time", "lt", 800] # 索引1
60
+ - ["response_time", "lt", 2500] # 索引1
61
61
  - ["jsonpath", "$.headers.Host", "eq", "httpbin.org"] # 索引2
62
62
  retry_assertions:
63
63
  # 全局设置
@@ -0,0 +1,55 @@
1
+ @name: API测试入门示例
2
+ @description: 演示基本的API接口测试用法
3
+ @tags: [API, HTTP, 入门]
4
+ @author: Felix
5
+ @date: 2024-01-01
6
+
7
+ # 基本GET请求
8
+ [HTTP请求],客户端:'default',配置:'''
9
+ method: GET
10
+ url: https://jsonplaceholder.typicode.com/posts/1
11
+ asserts:
12
+ - ["status", "eq", 200]
13
+ - ["jsonpath", "$.id", "eq", 1]
14
+ - ["jsonpath", "$.title", "exists"]
15
+ ''',步骤名称:'获取文章详情'
16
+
17
+ # 响应数据捕获与使用
18
+ [HTTP请求],客户端:'default',配置:'''
19
+ method: GET
20
+ url: https://jsonplaceholder.typicode.com/posts
21
+ request:
22
+ params:
23
+ userId: 1
24
+ captures:
25
+ first_post_id: ["jsonpath", "$[0].id"]
26
+ post_count: ["jsonpath", "$", "length"]
27
+ asserts:
28
+ - ["status", "eq", 200]
29
+ - ["jsonpath", "$", "type", "array"]
30
+ ''',步骤名称:'获取用户文章列表'
31
+
32
+ # 打印捕获的变量
33
+ [打印],内容:'第一篇文章ID: ${first_post_id}, 文章总数: ${post_count}'
34
+
35
+ # POST请求创建资源
36
+ [HTTP请求],客户端:'default',配置:'''
37
+ method: POST
38
+ url: https://jsonplaceholder.typicode.com/posts
39
+ request:
40
+ headers:
41
+ Content-Type: application/json
42
+ json:
43
+ title: 测试标题
44
+ body: 测试内容
45
+ userId: 1
46
+ captures:
47
+ new_post_id: ["jsonpath", "$.id"]
48
+ asserts:
49
+ - ["status", "eq", 201]
50
+ - ["jsonpath", "$.title", "eq", "测试标题"]
51
+ ''',步骤名称:'创建新文章'
52
+
53
+ @teardown do
54
+ [打印],内容:'API测试完成!'
55
+ end
@@ -0,0 +1,31 @@
1
+ @name: 断言功能示例
2
+ @description: 演示断言关键字的基本用法
3
+ @tags: [断言, 入门]
4
+ @author: Felix
5
+ @date: 2024-01-01
6
+
7
+ # 基本断言
8
+ [断言],条件:'1 + 1 == 2',消息:'基本算术断言失败'
9
+
10
+ # 数字比较
11
+ num1 = 10
12
+ num2 = 5
13
+ [断言],条件:'${num1} > ${num2}',消息:'数字比较断言失败'
14
+
15
+ # JSON数据处理
16
+ json_data = '{"user": {"name": "张三", "age": 30, "roles": ["admin", "user"]}}'
17
+
18
+ # JSON断言示例
19
+ [JSON断言],JSON数据:${json_data},JSONPath:'$.user.age',预期值:30,操作符:'==',消息:'JSON断言失败:年龄不匹配'
20
+
21
+ # 类型断言
22
+ [类型断言],值:${json_data},类型:'string',消息:'类型断言失败'
23
+
24
+ # 简单变量赋值和断言
25
+ result = 53
26
+ [打印],内容:'结果: ${result}'
27
+ [断言],条件:'${result} == 53',消息:'结果不正确'
28
+
29
+ @teardown do
30
+ [打印],内容:'断言测试完成!'
31
+ end
@@ -0,0 +1,24 @@
1
+ @name: 变量和循环示例
2
+ @description: 演示变量使用和循环结构
3
+ @tags: [变量, 循环, 入门]
4
+ @author: Felix
5
+ @date: 2024-01-01
6
+
7
+ # 基本变量定义和使用
8
+ name = "pytest-dsl"
9
+ version = "1.0.0"
10
+ [打印],内容:'测试框架: ${name}, 版本: ${version}'
11
+
12
+ # 循环结构示例
13
+ [打印],内容:'开始循环测试'
14
+ count = 3
15
+
16
+ for i in range(1, ${count}) do
17
+ [打印],内容:'循环次数: ${i}'
18
+ end
19
+
20
+ [打印],内容:'循环结束'
21
+
22
+ @teardown do
23
+ [打印],内容:'变量和循环测试完成!'
24
+ end
@@ -0,0 +1,9 @@
1
+ from pytest_dsl.core.auto_decorator import auto_dsl
2
+
3
+ @auto_dsl("./custom")
4
+ class TestCustomKeyword:
5
+ """自定义关键字测试
6
+
7
+ 此测试类将自动加载当前目录下的所有.auto文件
8
+ """
9
+ pass