2009-01-29 6 views
9

Je suis perplexe avec ce script de test:Pourquoi mes tests Perl échouent-ils avec `use encoding 'utf8'`?

#!perl 

use strict; 
use warnings; 
use encoding 'utf8'; 
use Test::More 'no_plan'; 

ok('áá' =~ m/á/, 'ok direct match'); 

my $re = qr{á}; 
ok('áá' =~ m/$re/, 'ok qr-based match'); 

like('áá', $re, 'like qr-based match'); 

Les trois tests échouent, mais je me attendais que la use encoding 'utf8' amélioreraient les deux le áá littéral et les qr regexps à base de chaînes de UTF8, et passant ainsi la tests.

Si je supprime la ligne use encoding les tests passent comme prévu, mais je ne peux pas comprendre pourquoi ils échoueraient en mode utf8. J'utilise perl 5.8.8 sur Mac OS X (version du système).

Répondre

18

N'utilisez pas le en utilisant le encoding pragma. C'est cassé. (Juerd Waalboer a donné un grand discours où il a mentionné cela à YAPC :: UE 2K8.)

Il fait au moins deux choses à la fois qui n'appartiennent pas ensemble:

  1. Il spécifie un codage pour votre source fichier.
  2. Il spécifie un encodage pour votre entrée/sortie de fichier.

Et pour ajouter des blessures à insulter il fait aussi # 1 de façon brisée: elle réinterprète \xNN séquences comme octets non décodés plutôt que de les traiter comme codepoints, et les décode, vous empêchant d'être en mesure d'exprimer les caractères En dehors de l'encodage que vous avez spécifié et en faisant votre code source signifie différentes choses en fonction de l'encodage. C'est juste étonnamment faux. Ecrivez votre code source en ASCII ou en UTF-8 uniquement. Dans le dernier cas, le utf8 pragma est la bonne chose à utiliser. Si vous ne voulez pas utiliser UTF-8, mais que vous voulez inclure des caractères non-ASCII, échappez-les ou décodez-les explicitement.

Utilisez les couches d'E/S de façon explicite ou définissez-les en utilisant open pragma pour que les E/S soient automatiquement transcodées correctement.

+1

Dans le passé, j'ai toujours utilisé 'utf8' et j'ai utilisé l'utf8 au cours de la dernière année. quelque part que 'use utf8' a été cassé et que je devrais utiliser' use encoding 'utf8''. Il semble que j'ai besoin de revoir toute la question à nouveau ... Merci – melo

2

Cela fonctionne très bien sur mon ordinateur (perl 5.10). Peut-être que vous devriez essayer de remplacer ce use encoding 'utf8' par use utf8.

Quelle version de perl utilisez-vous? Je pense que les anciennes versions avaient des bugs avec UTF-8 dans les expressions rationnelles.

+0

J'ai également changé 'use encoding 'utf8'' en' utf8' et cela a fonctionné pour moi sur 5.8.8 Linux – mpeters

2

Le Test::More documentation contient un correctif pour ce problème, que je viens de trouver aujourd'hui (et cette entrée montre plus haut dans les googles).

UTF8/"caractère large en version imprimée"

Si vous utilisez UTF8 ou d'autres caractères non-ASCII avec Test :: Plus vous pouvez obtenir un avertissement "Wide character in print". En utilisant binmode STDOUT, ": utf8" ne le résoudra pas. Test :: Builder (qui alimente Test :: More) duplique STDOUT et STDERR. Donc, tout changement à eux, y compris la modification de leurs disciplines de sortie, ne semblera pas par Test :: More. Le travail consiste à modifier directement les handles de fichiers utilisés par Test :: Builder.

my $builder = Test::More->builder; 
binmode $builder->output,   ":utf8"; 
binmode $builder->failure_output, ":utf8"; 
binmode $builder->todo_output, ":utf8"; 

J'ajouté ce petit morceau de mon code à boilerplate d'essai et il fonctionne un charme.

Questions connexes