Desenvolvimento orientado a testes para macros e módulos de python do Fontlab Studio 5.
A Fakelab é uma substituição do Fontlab Studio 5 para testar o código Python.
Tudo é implementado apenas para tornar os objetos do Fontlab importáveis fora do Fontlab Studio 5 e executar testes.
Sugere -se instalar fakelab em um ambiente virtual para que o Fontlab não importe acidentalmente o módulo falso ao executar os scripts no Fontlab Studio 5. Se você pode viver com os incompatibilitas entre o Python 2.7 e 3, também poderá executar fakelab no Python 3.
Salvar o VFBS não é suportado, pois o formato VFB não é público, mas você pode salvar objetos Font como JSON.
A implementação do Fakelab é baseada na inestimável referência da API FONTLAB/Python não oficial e da execução de scripts no Fontlab Studio e verifica o que eles fazem, além de travar o aplicativo.
Quando você ativou seu ambiente virtual:
$ pip install -e .FL é então importável fora do Fontlab Studio:
from FL import fl , Font
# Make an empty font
f = Font ()
# Add the font to the mock app
fl . Add ( f )
# Close the font
fl . Close () Se você estiver em execução em um ambiente virtual e precisar tornar os módulos FONTLAB importáveis, adicione um arquivo .pth no diretório de pacotes de sites do seu ambiente virtual:
# fl5modules.pth
/Users/<yourname>/Code/FLMacros/System/Modules
Fakelab é um trabalho em andamento e apenas implementado até onde eu precisava em meus próprios scripts. Eu tenho que admitir que a maior parte deles ainda não tem testes.
Se você encontrar um NotImplementedError ao escrever testes, é aqui que você pode se destacar em ajudar a melhorar esse projeto;) ficarei feliz em aceitar suas solicitações de tração. Como alternativa, abra um problema, compre -me um café e espero que meus filhos me deixem em paz para encontrar algum tempo para trabalhar em seu problema.
O desenvolvimento de scripts sem teste automatizado é realmente apenas para projetos muito pequenos. Para ter certeza dos resultados de um módulo ou script, você deve sempre escrever testes. Isso geralmente é feito usando pytest.
Vamos supor que você tenha um script do Fontlab para selecionar glifos contendo componentes. Se você tiver sua própria coleção de ferramentas para o Fontlab, esse script poderá consistir em duas partes: um script listado na barra de ferramentas do Fontlab e um módulo Python implementando a lógica, chamada pelo script da barra de ferramentas.
Studio 5
+- Macros
+- Selection
+- Select Composites.py
+- System
+- Modules
+- fakeLabDemo
+- selection
+- __init__.py
+- composites.py
O script Select Composites.py se parece com o seguinte:
#FLM: Select composites
# Studio 5/Macros/Selection/Select Composites.py
from fakeLabDemo . selection . composites import selectComposites
selectComposites ( fl . font )E o módulo:
# Studio 5/Macros/System/Modules/fakeLabDemo/selection/composites.py
from __future__ import absolute_import , division , print_function
from FL import fl
def getFontIndex ( font ):
"""
Get the index of the supplied font.
We must iterate through the open fonts and compare file names,
because the == operator can not compare the font objects directly.
(FL font objects get a different id() each time they are called)
:param font: A title for the dialog.
:type font: :py:class:`FL.Font`
"""
for i in range ( len ( fl )):
cf = fl [ i ]
if cf . file_name == font . file_name :
if font . file_name is None :
if (
cf . family_name == font . family_name
and cf . style_name == font . style_name
):
return ( cf , i )
else :
return ( cf , i )
# Font was not found, probably there are no open fonts
return ( None , - 1 )
def setSelection ( font , glyph_names ):
"""
Set glyphs from the glyph_names list as selected in the font window.
"""
f , i = getFontIndex ( font )
if i > - 1 :
fl . ifont = i
fl . Unselect ()
for n in glyph_names :
fl . Select ( n )
def selectComposites ( font ):
"""
Select composites in font.
"""
setSelection (
font ,
[
glyph . name
for glyph in font . glyphs
if glyph . components
]
)Como podemos ter certeza de que este script faz o que deve fazer? Para o Pytest, adicionamos outra estrutura de pasta paralela à estrutura existente:
Studio 5
+- Macros
+- Selection
+- Select Composites.py
+- System
+- Modules
+- fakeLabDemo
+- selection
+- __init__.py
+- composites.py
+- tests
+- fakeLabDemo
+- selection
+- composites_test.py
O arquivo composites_test.py , que é nomeado análogo ao arquivo do módulo com o qual se relaciona, é onde implementaremos nossos testes:
# Studio 5/Macros/System/Modules/tests/fakeLabDemo/selection/composites_test.py
import pytest
from FL import fl , Component , Font , Glyph , Point
from fakeLabDemo . selection . composites import selectComposites
def test_selectComposites ():
# Construct a fake FontLab font object
font = Font ()
g = Glyph ( 1 )
g . name = "A"
g . width = 500
g . unicode = 0x41
font . glyphs . append ( g )
g = Glyph ( 1 )
g . name = "dieresis"
g . width = 500
g . unicode = 0xA8
font . glyphs . append ( g )
g = Glyph ( 1 )
g . name = "Adieresis"
g . width = 500
g . unicode = 0xC4
g . components . append ( Component ( 0 ))
g . components . append ( Component ( 1 , Point ( 0 , 300 )))
font . glyphs . append ( g )
# Add the font to the FL object
fl . Add ( font )
fl . UpdateFont ()
# Run our script to be tested on the font
selectComposites ( fl . font )
# You could save the fake font to JSON instead of VFB.
# fl.font.Save("test_composites.vfb.json")
# Test if the correct glyphs have been selected
assert fl . Selected ( 0 ) == 0
assert fl . Selected ( 1 ) == 0
assert fl . Selected ( 2 ) == 1
# Close the fake font
fl . Close ()Como você vê, você pode usar os objetos exatamente como faria dentro do Fontlab. Você simplesmente não pode abrir uma fonte de um VFB existente, o que seria muito mais fácil. Mas o formato de arquivo VFB não é público.
Em vez disso, você deve construir uma fonte de teste usando a API FL Python.
Invoque o script de teste em uma janela de terminal enquanto seu ambiente virtual estiver ativo:
cd " Studio 5/Macros/System/Modules "
python -m pytest tests/fakeLabDemo/selection/composites_test.pySe tudo der certo, você verá alguma saída como esta:
============================ test session starts ===============================
platform darwin -- Python 3.8.7, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: /Users/jens/Code/fakelab
collected 1 item
tests/fakeLabDemo/selection/composites_test.py . [100%]
============================= 1 passed in 0.02s ================================