import pytest


class CodeCollector:
    """Dedicated decorator to use functions as Py.Test function parameters."""

    def __init__(self, name="code"):

        self.name = name
        self.collected = []

    def __call__(self, f):
        """Mark decorated function as a test parameter."""
        self.collected.append(f)
        return f

    def xfail(self, f):
        """Mark function as a test parameter with expected failure."""
        return self(pytest.param(f, marks=pytest.mark.xfail))

    def __iter__(self):
        return iter(self.collected)

    def parametrize(self, test_func):
        """Parametrize decorated test function with collected functions."""
        return pytest.mark.parametrize(self.name, self)(test_func)

@@ -1,8 +1,37 @@
+import random%0Aimport string%0A%0A
 import p
@@ -176,17 +176,16 @@
 code%22):%0A
-%0A
         
@@ -230,16 +230,214 @@
 d = %5B%5D%0A%0A
+    def parametrize(self, test_func):%0A        %22%22%22Parametrize decorated test function with collected functions.%22%22%22%0A        return pytest.mark.parametrize(self.name, iter(self.collected))(test_func)%0A%0A
     def 
@@ -531,24 +531,17 @@
 elf.
-collected.append
+_validate
 (f)%0A
@@ -555,17 +555,28 @@
  return 
-f
+self._add(f)
 %0A%0A    de
@@ -660,24 +660,50 @@
 failure.%22%22%22%0A
+        self._validate(f)%0A
         retu
@@ -709,16 +709,21 @@
 urn self
+._add
 (pytest.
@@ -771,20 +771,24 @@
 ef _
-_iter__
+validate
 (self
+, f
 ):%0A 
@@ -798,20 +798,79 @@
     
-return iter(
+function_name = f.__name__%0A        _validate_uniqueness(function_name, 
 self
@@ -885,186 +885,1315 @@
 ed)%0A
-%0A
     
-def parametrize(self, test_func):%0A        %22%22%22Parametrize deco
+    _validate_length(function_name)%0A        _validate_prefix(function_name)%0A        _validate_tail(function_name)%0A%0A    def _add(self, arg):%0A        self.collected.append(arg)%0A        return arg%0A%0A%0Adef _validate_uniqueness(name, collection):%0A    if name in collection:  # pragma: no cover%0A        raise Exception(f%22%7Bname%7D was already collected%22)%0A%0A%0Adef _validate_length(name):%0A    if len(name) != 13:  # pragma: no cover%0A        raise Exception(f%22%7Bname%7D should be 13 cha
 ra
+c
 te
-d test function with collected functions.%22%22%22%0A        return pytest.mark.parametrize(self.name, self)(test_func
+rs long%22)%0A%0A%0Adef _validate_prefix(name):%0A    if not name.startswith(%22_%22):  # pragma: no cover%0A        raise Exception(f%22%7Bname%7D should be a private function%22)%0A%0A%0Adef _validate_tail(name):%0A    for char in name%5B1:%5D:%0A        if char not in string.ascii_letters + string.digits:  # pragma: no cover%0A            suggested = _suggest()%0A            message = wrong_name_template.format(%0A                function_name=name, suggested=suggested%0A            )%0A            raise Exception(message)%0A%0A%0Adef _suggest():  # pragma: no cover%0A    return (%0A        %22_%22%0A        + random.choice(string.ascii_lowercase)%0A        + %22%22.join(%0A            random.choice(string.ascii_letters + string.digits) for _ in range(11)%0A        )%0A    )%0A%0A%0A# Messages.%0A%0A%0Awrong_name_template = %22%22%22%0A%7Bfunction_name%7D should a have random name.%0A%0AHow about %7Bsuggested!r%7D%0A%22%22%22.strip(
 )%0A

validate CodeCollector arguments #386