gabrielfalcao/lettuce — pull request #256 by jangxyz (2012-06-09 09:43:14+00:00)
Title: unicode problems when fail

Hi.

Lettuce tries to show verbose error message when a step fails,
but gets mangled up when exception is raised during the process.
The result are more catastrophic exceptions like `UnicodeDecodeError` or `step.why` being `None` and dying with `SystemExit: 2`
I've experienced some issues with unicode handling, so came up with a patch.

I haven't come up with unit tests, but a feature to test

```cucumber
Feature: Reveal error in non-ascii code
In order to work better with lettuce
As a non-ascii speaker
I want to see nice exception messages

Scenario: Factorial of 4
Given I have the number 4
When I compute its factorial
Then I see the number 24
And it is fine

Scenario: Error on line with ascii letters
When I have error on ascii encoding line

Scenario: Error on non-ascii code
When I have error on non-ascii encoding line

Scenario: Error on non-ascii unicode
When I have error on non-ascii encoding unicode line

Scenario: Error on non-ascii comment
When I have error on non-ascii encoding comment

Scenario: Pass with non-ascii step
When I 패스 with non-ascii step
Then it is fine

Scenario: Error on non-ascii step
When I have 에러 on non-ascii step

Scenario: non-ascii letter on cause
When I have non-ascii letter on cause
```

```python
#!/usr/bin/python
# -*- coding: utf8 -*-

from lettuce import *

@step('I have the number (\d+)')
def have_the_number(step, number):
world.number = int(number)

@step('I compute its factorial')
def compute_its_factorial(step):
world.number = factorial(world.number)

@step('I see the number (\d+)')
def check_number(step, expected):
expected = int(expected)
assert world.number == expected, \
"Got %d" % world.number

def factorial(number):
if number != 0:
return number * factorial(number-1)
return 1

#
#
#

class NormalCase(Exception):
pass

def make_error(msg=None):
raise NormalCase(msg or "this is normal.")

@step(u'it is fine')
def fine(step):
return True

#

@step(u'I have error on ascii encoding line')
def error_on_ascii_code(step):
make_error()

@step(u'I have error on non-ascii encoding line')
def error_on_non_ascii_code(step):
make_error() == '익셉션'

@step(u'I have error on non-ascii encoding unicode line')
def error_on_unicode(step):
make_error(u'한글이 있다면 어떨까.')

@step(u'I have error on non-ascii encoding comment')
def error_on_non_ascii_comment(step):
make_error() # 익셉션

#

@step(u'I 패스 with non-ascii step')
def pass_with_non_ascii_step(step):
return True

@step(u'I have 에러 on non-ascii step')
def error_on_non_ascii_step(step):
make_error()

@step(u'I have non-ascii letter on cause')
def error_on_cause(step):
msg = '한글 메시지'
assert msg == 'not same', "%s is not same with %s" % (msg, 'not same')
```