Feature: Internationalization (i18n) and Problems with Unicode Strings . POTENTIAL PROBLEM AREAS: . * Feature, scenario, step names with problematic chars . * Tags with problematic chars . * step raises exception with problematic text (output capture) . * step generates output with problematic and some step fails (stdout capture) . * filenames with problematic chars: feature files, steps files . . CHECKED FORMATTERS and REPORTERS: . * plain . * pretty . * junit (used via "behave.ini" defaults) @setup Scenario: Feature Setup Given a new working directory And a file named "behave.ini" with: """ [behave] show_timings = false show_skipped = false show_source = true junit = true """ And a file named "features/steps/passing_steps.py" with: """ # -*- coding: UTF-8 -*- from behave import step @step(u'{word:w} step passes') def step_passes(context, word): pass @step(u'{word:w} step passes with "{text}"') def step_passes_with_text(context, word, text): pass @step(u'{word:w} step fails') def step_fails(context, word): assert False, "XFAIL" @step(u'{word:w} step fails with "{text}"') def step_fails_with_text(context, word, text): assert False, u"XFAIL: "+ text """ And a file named "features/steps/step_write_output.py" with: """ # -*- coding: UTF-8 -*- from __future__ import print_function from behave import step import six @step(u'I write text "{text}" to stdout') def step_write_text(context, text): if six.PY2 and isinstance(text, six.text_type): text = text.encode("utf-8", "replace") print(text) @step(u'I write bytes "{data}" to stdout') def step_write_bytes(context, data): if isinstance(data, six.text_type): data = data.encode("unicode-escape", "replace") print(data) """ Scenario Outline: Problematic scenario name: <scenario.name> (case: passed, <format>) Given a file named "features/scenario_name_problematic_and_pass.feature" with: """ Feature: Scenario: <scenario.name> Given a step passes """ When I run "behave -f <format> features/scenario_name_problematic_and_pass.feature" Then it should pass with: """ 1 feature passed, 0 failed, 0 skipped 1 scenario passed, 0 failed, 0 skipped """ And the command output should contain: """ Scenario: <scenario.name> """ Examples: | format | scenario.name | | plain | Café | | pretty | Ärgernis ist überall | Scenario Outline: Problematic scenario name: <scenario.name> (case: failed, <format>) Given a file named "features/scenario_name_problematic_and_fail.feature" with: """ Feature: Scenario: <scenario.name> Given a step fails """ When I run "behave -f <format> features/scenario_name_problematic_and_fail.feature" Then it should fail with: """ 0 features passed, 1 failed, 0 skipped 0 scenarios passed, 1 failed, 0 skipped """ And the command output should contain: """ Scenario: <scenario.name> """ Examples: | format | scenario.name | | plain | Café | | pretty | Ärgernis ist überall | Scenario Outline: Problematic step: <step.text> (case: passed, <format>) Given a file named "features/step_problematic_and_pass.feature" with: """ Feature: Scenario: Given a step passes with "<step.text>" """ When I run "behave -f <format> features/step_problematic_and_pass.feature" Then it should pass with: """ 1 feature passed, 0 failed, 0 skipped 1 scenario passed, 0 failed, 0 skipped 1 step passed, 0 failed, 0 skipped, 0 undefined """ Examples: | format | step.text | | plain | Café | | pretty | Ärgernis ist überall | Scenario Outline: Problematic step: <step.text> (case: fail, <format>) Given a file named "features/step_problematic_and_fail.feature" with: """ Feature: Scenario: Given a step fails with "<step.text>" """ When I run "behave -f <format> features/step_problematic_and_fail.feature" Then it should fail with: """ 0 features passed, 1 failed, 0 skipped 0 scenarios passed, 1 failed, 0 skipped 0 steps passed, 1 failed, 0 skipped, 0 undefined """ Examples: | format | step.text | | plain | Café | | pretty | Ärgernis ist überall | @problematic.feature_filename @not.with_os=win32 Scenario Outline: Problematic feature filename: <name> (case: pass, <format>) Given a file named "features/<name>_and_pass.feature" with: """ Feature: Scenario: Given a step passes """ When I run "behave -f <format> features/<name>_and_pass.feature" Then it should pass with: """ 1 feature passed, 0 failed, 0 skipped 1 scenario passed, 0 failed, 0 skipped """ Examples: | format | name | | plain | Café | | pretty | Ärgernis_ist_überall | @problematic.feature_filename @not.with_os=win32 Scenario Outline: Problematic feature filename: <name> (case: fail, <format>) Given a file named "features/<name>_and_fail.feature" with: """ Feature: Scenario: Given a step fails """ When I run "behave -f <format> features/<name>_and_fail.feature" Then it should fail with: """ 0 features passed, 1 failed, 0 skipped 0 scenarios passed, 1 failed, 0 skipped """ Examples: | format | name | | plain | Café | | pretty | Ärgernis_ist_überall | @problematic.step_filename Scenario Outline: Problematic step filename: <name> (case: pass, <format>) TEST-CONSTRAINT: Only one step file is used (= 1 name only). Otherwise, duplicated steps occur (without cleanup in step directory). Given a file named "features/problematic_stepfile_and_pass.feature" with: """ Feature: Scenario: Given I use a weird step and pass """ And a file named "features/steps/step_pass_<name>.py" with: """ from behave import step @step(u'I use a weird step and pass') def step_weird_pass(context): pass """ When I run "behave -f <format> features/problematic_stepfile_and_pass.feature" Then it should pass with: """ 1 feature passed, 0 failed, 0 skipped 1 scenario passed, 0 failed, 0 skipped """ But note that "you should normally use only ASCII/latin-1 python filenames" Examples: | format | name | | plain | Ärgernis_ist_überall | | pretty | Ärgernis_ist_überall | @problematic.step_filename Scenario Outline: Problematic step filename: <name> (case: fail, <format>) TEST-CONSTRAINT: Only one step file is used (= 1 name only). Otherwise, duplicated steps occur (without cleanup in step directory). Given a file named "features/problematic_stepfile_and_fail.feature" with: """ Feature: Scenario: Given I use a weird step and fail """ And a file named "features/steps/step_fail_<name>.py" with: """ from behave import step @step(u'I use a weird step and fail') def step_weird_fails(context): assert False, "XFAIL-WEIRD" """ When I run "behave -f <format> features/problematic_stepfile_and_fail.feature" Then it should fail with: """ 0 features passed, 1 failed, 0 skipped 0 scenarios passed, 1 failed, 0 skipped """ But note that "you should normally use only ASCII/latin-1 python filenames" Examples: | format | name | | plain | Ärgernis_ist_überall | | pretty | Ärgernis_ist_überall | @problematic.output Scenario Outline: Problematic output: <text> (case: pass, <format>) Given a file named "features/problematic_output_and_pass.feature" with: """ Feature: Scenario: Given I write text "<text>" to stdout Then I write bytes "<text>" to stdout And a step passes """ When I run "behave -f <format> --no-capture features/problematic_output_and_pass.feature" Then it should pass with: """ 1 feature passed, 0 failed, 0 skipped 1 scenario passed, 0 failed, 0 skipped """ Examples: | format | text | | plain | Café | | pretty | Ärgernis ist überall | @problematic.output Scenario Outline: Problematic output: <text> (case: fail, <format>) Given a file named "features/problematic_output_and_fail.feature" with: """ Feature: Scenario: Given I write text "<text>" to stdout Then I write bytes "<text>" to stdout And a step fails """ When I run "behave -f <format> features/problematic_output_and_fail.feature" Then it should fail with: """ 0 features passed, 1 failed, 0 skipped 0 scenarios passed, 1 failed, 0 skipped """ And the command output should contain: """ <text> """ Examples: | format | text | | plain | Café | | pretty | Ärgernis ist überall | @problematic.tags Scenario Outline: Problematic tag: <tag> (case: pass, <format>) Given a file named "features/problematic_tag_and_pass.feature" with: """ Feature: @<tag> Scenario: Given a step passes """ When I run "behave -f <format> features/problematic_tag_and_pass.feature" Then it should pass with: """ 1 scenario passed, 0 failed, 0 skipped """ Examples: | format | tag | | plain | tag.Café | | pretty | tag.Ärgernis_ist_überall | @problematic.tags Scenario Outline: Problematic tag: <tag> (case: fail, <format>) Given a file named "features/problematic_tag_and_fail.feature" with: """ Feature: @<tag> Scenario: Given a step fails """ When I run "behave -f <format> features/problematic_tag_and_fail.feature" Then it should fail with: """ 0 scenarios passed, 1 failed, 0 skipped """ Examples: | format | tag | | plain | tag.Café | | pretty | tag.Ärgernis_ist_überall | @issue_0230 Scenario Outline: Step assert fails with problematic chars (case: <format>) NOTE: Python2 fails silently without showing the failed step. HINT: Use unicode string when you use, special non-ASCII characters. HINT: Use encoding-hint in python file header. Given a file named "features/steps/problematic_steps.py" with: """ # -*- coding: UTF-8 -*- from behave import step @step(u'{word:w} step fails with assert and non-ASCII text') def step_fails_with_assert_and_problematic_text(context, word): assert False, u"XFAIL:¾;" """ And a file named "features/assert_with_ptext.feature" with: """ Feature: Scenario: Given a step passes When a step fails with assert and non-ASCII text """ When I run "behave -f <format> features/assert_with_ptext.feature" Then it should fail with: """ 0 scenarios passed, 1 failed, 0 skipped 1 step passed, 1 failed, 0 skipped, 0 undefined """ And the command output should contain: """ Assertion Failed: XFAIL:¾; """ Examples: | format | | plain | | pretty | @issue_0226 Scenario Outline: Step raises exception with problematic chars (case: <format>) In Python2: When an exception is raised with unicode argument, (and special non-ASCII chars) the conversion of the exception into a unicode string causes implicit conversion into a normal string by using the default encoding (normally: ASCII). Therefore, the implicit encoding into a normal string often fails. SEE ALSO: http://bugs.python.org/issue2517 NOTE: Better if encoding hint is provided in python file header. Given a file named "features/steps/problematic_steps.py" with: """ # -*- coding: UTF-8 -*- from behave import step @step(u'{word:w} step fails with exception and non-ASCII text') def step_fails_with_exception_and_problematic_text(context, word): # -- REQUIRE: UNICODE STRING, when special, non-ASCII chars are used. raise RuntimeError(u"FAIL:¾;") """ And a file named "features/exception_with_ptext.feature" with: """ Feature: Scenario: Given a step passes When a step fails with exception and non-ASCII text """ When I run "behave -f <format> features/exception_with_ptext.feature" Then it should fail with: """ 0 scenarios passed, 1 failed, 0 skipped 1 step passed, 1 failed, 0 skipped, 0 undefined """ And the command output should contain: """ RuntimeError: FAIL:¾; """ Examples: | format | | plain | | pretty |