Permalink
Browse files

Test and fix extension loading components

  • Loading branch information...
1 parent af88107 commit 90fbd53eebcacbe9d7456d4a4e66b3743a288bd5 @svanoort committed Dec 4, 2014
Showing with 53 additions and 22 deletions.
  1. +18 −2 extension_use_test.yaml
  2. +2 −2 pyresttest/resttest.py
  3. +10 −5 pyresttest/validators.py
  4. +23 −13 sample_extension.py
@@ -2,12 +2,28 @@
---
- config:
- testset: "Simple github.com API Test with custom validator"
+ - generators:
+ - 'number' : {type: 'doubling', start: 8}
- test:
- name: "Test with successful validations"
- url: "/search/users?q=jewzaam"
- group: "Successful"
- validators:
- contains: 'subscriptions_url'
- #- extract_test: {jsonpath_mini: 'items', test: 'has_braces'}
+ - extract_test: {jsonpath_mini: 'items.0', test: 'is_dict'}
- compare: {jsonpath_mini: 'items.0.login', comparator: 'str.eq.lower', expected: 'JewZaam'}
- #- extract_test: {'weirdzo': 'blah', test: 'exists'}
+ - extract_test: {'weirdzo': 'blah', test: 'exists'}
+- test:
+ - generator_binds: {num: number}
+ - name: "Test with generator"
+ - url: {template: "/search/users?q=$num&in=id"}
+ - group: "Successful"
+ - validators:
+ - compare: {jsonpath_mini: 'items.0.login', comparator: 'contains', expected: '8'}
+- test:
+ - generator_binds: {num: number}
+ - name: "Test with generator run 2"
+ - url: {template: "/search/users?q=$num&in=id"}
+ - group: "Successful"
+ - validators:
+ - compare: {jsonpath_mini: 'items.0.login', comparator: 'contains', expected: '16'}
@@ -591,9 +591,9 @@ def register_extensions(modules):
# Extensions are registered by applying a register function to sets of registry name/function pairs inside an object
extension_applies = {
'VALIDATORS': validators.register_validator,
- 'VALIDATOR_COMPARATORS': validators.register_comparator,
+ 'COMPARATORS': validators.register_comparator,
'VALIDATOR_TESTS': validators.register_test,
- 'VALIDATOR_EXTRACTORS': validators.register_extractor,
+ 'EXTRACTORS': validators.register_extractor,
'GENERATORS': generators.register_generator
}
@@ -203,14 +203,14 @@ def _get_extractor(config_dict):
if key in EXTRACTORS:
return parse_extractor(key, value)
else: # No valid extractor
- return None
+ raise Exception('No valid extractor name to use in input: {0}'.format(config_dict))
class AbstractValidator(object):
""" Encapsulates basic validator handling """
name = None
config = None
- def validate(self, body, context=None):
+ def validate(self, body=None, headers=None, context=None):
""" Run the validation function, return true or a ValidationFailure """
pass
@@ -227,7 +227,7 @@ class ComparatorValidator(AbstractValidator):
def validate(self, body=None, headers=None, context=None):
try :
- extracted_val = self.extractor.extract(body, context=context)
+ extracted_val = self.extractor.extract(body=body, headers=headers, context=context)
except Exception as e:
return ValidationFailure(message="Extractor threw exception", details=e, validator=self)
@@ -327,9 +327,9 @@ def parse(config):
output.test_fn = test_fn
return output
- def validate(self, body, context=None):
+ def validate(self, body=None, headers=None, context=None):
try:
- extracted = self.extractor.extract(body, context=context)
+ extracted = self.extractor.extract(body=body, headers=headers, context=context)
except Exception as e:
return ValidationFailure(message="Exception thrown while running extraction from body", details=e, validator=self)
@@ -355,6 +355,11 @@ def parse_extractor(extractor_type, config):
if isinstance(parsed, AbstractExtractor): # Parser gave a full extractor
return parsed
+
+ # Look for matching attributes... simple inheritance has issues because of cross-module loading
+ items = AbstractExtractor().__dict__
+ if set(parsed.__dict__.keys()).issuperset(set(items.keys())):
+ return parsed
else:
raise TypeError("Parsing functions for extractors must return an AbstractExtractor instance!")
View
@@ -25,13 +25,10 @@ def parse(config):
validator.contains_string = config
return validator
-def test_has_braces(input_string):
- """ Test if input string contains a brace ({}) """
- return '{' in input_string or '}' in input_string
-
-
class WeirdzoExtractor(validators.AbstractExtractor):
- extractor_type = 'weirdozo'
+ """ Always returns 'zorba' """
+
+ extractor_type = 'weirdzo'
is_body_extractor = True
@classmethod
@@ -44,17 +41,30 @@ def parse(cls, config, extractor_base=None):
def extract_internal(self, query=None, args=None, body=None, headers=None):
return 'zorba'
+def parse_generator_doubling(config):
+ """ Returns generators that double with each value returned, config includes start value """
+ start = 1
+ if 'start' in config:
+ start = int(config['start'])
-def parse_extractor_weirdzo(config):
- """ Parser for extractor config that always ignores config
- and returns the extract_weirdzo function """
- return extract_weirdzo
+ # We cannot simply use start as the variable, because of scoping limitations
+ def generator():
+ val = start
+ while(True):
+ yield val
+ val = val*2
+ return generator()
+def test_is_dict(input):
+ """ Simple test that returns true if item is a dictionary """
+ return isinstance(input, dict)
# This is where the magic happens, each one of these is a registry of validators/extractors/generators to use
VALIDATORS = {'contains': ContainsValidator.parse}
-VALIDATOR_TESTS = {'has_braces': test_has_braces}
+VALIDATOR_TESTS = {'is_dict': test_is_dict}
+
# Converts to lowercase and tests for equality
-VALIDATOR_COMPARATORS = {'str.eq.lower': lambda a,b: str(a).lower() == str(b).lower()}
+COMPARATORS = {'str.eq.lower': lambda a,b: str(a).lower() == str(b).lower()}
-EXTRACTORS = {'weirdzo': WeirdzoExtractor.parse}
+EXTRACTORS = {'weirdzo': WeirdzoExtractor.parse}
+GENERATORS = {'doubling': parse_generator_doubling}

0 comments on commit 90fbd53

Please sign in to comment.