lettuce icon indicating copy to clipboard operation
lettuce copied to clipboard

Silently fails when "Backgound" has step with accent "ñ"

Open doup opened this issue 9 years ago • 8 comments

Note the ñ in Contexto, changing that it just works. If I put password instead of contraseña it works.

# language: es
Funcionalidad: Login
    Como usuario invitado (Guest)
    Quiero poder hacer login
    Para poder acceder a la parte privada de GestioCI

    Contexto:
        Dado que existe un usuario "user" con contraseña "pass"

    Escenario: Si no estas logeado la aplicación te redigire a la pantalla de login
        Dado que no estoy logeado
        Cuando accedo a "/"
        Entonces termino en "/login/?next=/"

It just silently fails:

$ ./manage.py harvest
Creating test database for alias 'default'...
Django's builtin server is running at 0.0.0.0:8000

Funcionalidad: Login                                    # django-project/apps/inici/features/login.feature:3
  Como usuario invitado (Guest)                         # django-project/apps/inici/features/login.feature:4
  Quiero poder hacer login                              # django-project/apps/inici/features/login.feature:5
  Para poder acceder a la parte privada de GestioCI     # django-project/apps/inici/features/login.feature:6

  Background:

0 feature (0 passed)
0 scenario (0 passed)
0 step (0 passed)

Test Suite Summary:
0 feature (0 passed)
0 scenario (0 passed)
0 step (0 passed)
Destroying test database for alias 'default'...

doup avatar Mar 30 '15 11:03 doup

Can you show the corresponding step file?

michelts avatar Mar 30 '15 11:03 michelts

@michelts here you have. The step is at the bottom.

If I change contraseña for password in both the terrain.py and in the feature it works.

# terrain.py
# -*- coding: utf-8 -*-
# ...

@steps
class CoreSteps(object):
    """
    Methods in exclude or starting with _
    will not be considered as step
    """
    exclude = []

    def __init__(self, env, tc):
        self.env = env
        self.tc = tc

    def existe_un_usuario(self, step, username, password):
        '''.* existe un usuario "([^"]*)" con contraseña "([^"]*)"'''
        from django.contrib.auth.models import User
        User.objects.create_user(username=username, password=password)

    # ...

CoreSteps(world, TestCase('__init__'))

doup avatar Mar 30 '15 11:03 doup

I use functions instead classes to define steps, but I suspect the problem is at the step regular expression. Can you try using an unicode string? For instance:

    def existe_un_usuario(self, step, username, password):
        u'''.* existe un usuario "([^"]*)" con contraseña "([^"]*)"'''
        from django.contrib.auth.models import User
        User.objects.create_user(username=username, password=password)

Another way to figure out these type of problems it to write te context in the scenario at first and, when the context if passing, I move it from scenario to context again. This is not the fix for the bug related here, but can help you use lettuce until it is fixed!

michelts avatar Mar 30 '15 11:03 michelts

Thanks! using u fixed it. I'm closing the issue, since I suppose it's more a Python 2.x thing than a bug.

doup avatar Mar 30 '15 12:03 doup

I don't agree. It is a bug since lettuce fails silently. It should tell the step was not found for contexts too. Try the same approach in a scenario instead of a context...

michelts avatar Mar 30 '15 12:03 michelts

True. I misunderstood your previous comment.

doup avatar Mar 30 '15 12:03 doup

When a step fails in "Background" (for example because of a NoDefinitionFound exception), the exception is caught by Runner.run(...) and printed out directly which raises a UnicodeEncodeError exception.

This exception is hidden by the finally statement which returns an empty list (as if there wasn't any scenario in the file)...

If you run lettuce using the --failfast flag, you'll notice the error but the failure won't be taken into account when we set the exit code.

hectord avatar May 31 '15 15:05 hectord

Ok... so it's not as easy as I excepted. Python 2 is not designed to handle non-ASCII characters in exception messages (see [1]).

There are several possibilities to fix that but I don't like any of them:

  1. We filter out the non-ASCII characters before raising the exception
  2. We use Python Kitchen to wrap sys.stderr and sys.stdout and we encode the exception's message
  3. We change the default encoding (see [2]). This is considered as "downright wrong" by a Python Core Developer...

Whatever our choice, our english-speaking friends won't appreciate seeing their code rotten with hacks to cope with foreign languages...

This bug is not as catastrophical as it looks like because the exit code is defined correctly (even if nothing is printed out in verbose mode...).

Last idea: we could mention the error in the summary at the end of the output.

[1] https://pythonhosted.org/kitchen/unicode-frustrations.html (Frustration #5: Exceptions). [2] http://stackoverflow.com/questions/11741574/how-to-print-utf-8-encoded-text-to-the-console-in-python-3

hectord avatar Jun 01 '15 20:06 hectord