Apresentando Lettuce, BDD em python

Depois de muitas horas de hacking intenso, venho apresentar a primeira release candidate do Lettuce.

Trata-se de uma ferramenta de BDD 100% baseada no Cucumber.

O nome teve duas motivações:

  • Lettuce (Alface) é um vegetal verde, assim como Cucumber (Pepino), a idéia é que os testes sempre estejam verdes :)
  • Letuce é também o nome de uma banda à qual tenho muita admiração.

Mãos ao código

Deixei links para a documentação no fim deste post, mas aqui vai uma prévia:

Funcionalidades são descritas em arquivos com a extensão .feature, e devem ficar por padrão, dentro do seu projeto, chamada features

Por sua vez, features são descritas assim:

Feature: Introduce lettuce to my friends
  In order to show it working
  As lettuce author
  I want to create a scenario that passes

  Scenario: Concatenate names
    Given I have the following names:
      | name | surname |
      | john | doe     |
      | ian  | murdock |
    When I join them
    Then I see the data:
      | joined       |
      | Doe, John    |
      | Murdock, Ian |

Para implementar as steps, basta criar um arquivo python qualquer dentro da pasta features o Lettuce importará todos eles recursivamente.
Exemplo:

# -*- coding: utf-8 -*-
from lettuce import step, world, before
from some_module import NameJoiner

# setup
@before.each_scenario
def set_joined(scenario):
    world.joined = []

# steps
@step('I have the following names')
def set_names(step):
    world.people = step.hashes

@step('join them')
def join_names(step):
    for person in world.people:
        joiner = NameJoiner(
            name=person["name"],
            surname=person["surname"]
        )
        world.joined.append(joiner.join())

@step('I see the data')
def check_names(step):
    for name, data in zip(world.joined, step.hashes):
        assert name == data['joined']

(baixe o exemplo completo aqui)

Motivação

Desde que comecei a praticar TDD em Python tive várias experiências, testei várias bibliotecas de mock e técnicas de teste.
Em projetos de aplicações web usei o Pyccuracy, assim podia descrever o comportamento da aplicação ao mesmo tempo que fazia testes automatizados da interface.

No entanto, tive a chance de testar o  Cucumber num projeto Django aqui na globo.com, me apaixonei por funcionalidades incrivelmente produtivas, como step tables que permite desenhar uma tabela com caracteres, e mapear como lista de hashes, bem como scenario outlines.

Daí veio a grande inspiração: implementar uma ferramenta como o Cucumber, mas em python puro.

Por que?
Para programadores python, é mais cômodo usar bibliotecas em python puro. Eu pessoalmente evito misturar linguagens, a não ser que a melhor solução seja realmente em outra linguagem.

Cucumber é, na minha opinião, uma lib que torna ruby ainda mais sexy :)
Criar uma aplicação robusta, bem testada requer paciência, que tal tornar isso mais divertido ?
É mais fácil empacotar módulos python para debian/ubuntu :P

Além disso, apesar de Cucumber dar suporte a Python, seria interessante usar python puro dentro das step definitions.
Supondo o desenvolvimento de uma aplicação Django com cucumber, seria útil manipular os models dentro de step definitions. Entretanto, para isso acontecer, é necessário usar algo como rubypython, cuja última release data outubro de 2009.

Exemplos de bibliotecas similares/equivalentes entre python e ruby

Framework web:

ruby: rails
python: django

Micro-framework web:

ruby: sinatra
python: cherrypy

Deploy automatizado:

ruby: capistrano
python: fabric

Behaviour-driven development:

ruby: cucumber
python: lettuce ?! (quem sabe :P )

Direto ao assunto!

Hoje estou liberando oficialmente a primeira release candidate do Lettuce, que atualmente possui as seguintes features:

  • Hooks pre/pós execução de:
    • Toda a suíte de testes
    • Cada feature
    • Cada scenario
    • Cada step
  • Contexto global: world
  • Scenario outlines
  • Step tables
  • Nomes e formato de arquivo de features compatível com cucumber
  • Output colorido
  • Output sem cor

Mas… O que falta para fechar a primeira release oficial? Além de ter feedback sobre possíveis bugs das features já implementadas para melhorá-las, a intenção é que a primeira release também tenha as seguintes funcionalidades:

Documentação

Não poderia faltar, mas ainda está sendo escrita.
De qualquer forma, já possui o básico para colocar o um novo projeto funcionando. E se você já conhece o Cucumber, não terá dificuldades.

Acesse a documentação aqui

Ou melhor ainda, vá direto ao “quick start”

Contribua!

Estou sedento por feedbacks (negativos e positivos), sendo assim:

Por fim, o lettuce está sob GNU GPL 3+ e ainda tem um longo caminho pela frente. Toda forma de ajuda é bem vinda, seja com patches, documentação, suporte para outros idiomas, etc.

Happy hacking :)

16 Responses to “Apresentando Lettuce, BDD em python”

  1. Taciano disse:

    Confesso que ainda não tenho prática com TDD (ou BDD) e Python, mas pretendo estudar mais o assunto.
    Agora achei uma boa oportunidade pra estudá-lo juntamente com sua ferramenta!
    Parabéns pelo projeto!

  2. Ainda não tive tempo de trabalhar com TDD ou BDD pra valer, mas achei muito interessante o seu POST e seu trabalho.

    Com certeza vou testar, parábens!

  3. Andei blogando sobre isso um tempo atrás.

    Existe outro framework de BDD em Python 100% baseado no Cucumber, o Freshen: http://github.com/rlisagor/freshen

    Parabéns pela iniciativa! ;)

  4. Renato Albano disse:

    Eu gostei da solução para descrever os ‘steps’ com anotations, ficou bem higiênica.
    Cheguei a ver o pessoal tentando dar umas soluções para DSL em python, mas anotation não chega tirar a expressividade.
    Irei testar!

  5. Bem interessante, já vou testar !

    Uma microframework que estou achando BEM interessante para python é o http://flask.pocoo.org/

    pra animar o pessoal a visitar vou até colar o hello world da home deles =)

    from flask import Flask
    app = Flask(__name__)

    @app.route(“/”)
    def hello():
    return “Hello World!”

    if __name__ == “__main__”:
    app.run()

  6. Robson Cardoso dos Santos disse:

    Cara, fantástico, eu já tinha ouvido falar nisso mas nunca estudei a fundo, seu post foi decisivo e agora vou atrás, muito bom. Aliás, hoje mesmo vou empacotá-lo para o Arch Linux.
    Abraços.

  7. wancharle disse:

    Pessoal,

    Sempre quiz programar com testes… Sempre que procuro acho sites como esse explicando ferramentas… Gostaria que alguem me indica-se algum livro ou fonte online onde posso aprender a usar a metodologi, principalmente no desenvolvimento de sistemas online e sites.

    até mais.

  8. Gabriel Falcão disse:

    Olá wancharle!

    Eu aconselho dar uma olhada nos screencasts do cucumber (http://cukes.info), na seção “cukes tv”

    Te aconselho especialmente este: http://www.teachmetocode.com/screencasts/4

    Sobre desenvolvimento “outside-in”

  9. wancharle disse:

    Obrigado,
    Valeu pelo link!

  10. Samir Mamude disse:

    Parabéns pelo trabalho!

    Gostaria de saber se é possível escrever testes num projeto onde o frontend é baseado no ExtJs e backend Python? Já testei algumas alternativas como o Selenium, mas não achei amigável, já tive contato com o Cucumber e realmente torna bem prático escrever testes. Se for possível isso com Lettuce vai resolver meu problema :)

    Abs,
    Samir

  11. Gabriel Falcão disse:

    Olá Samir!

    Então, você pode usar selenium, webdriver ou windmill.
    Mas em python ainda não encontrei nenhuma ferramenta que seja tão simples e amigável quanto ao Watir[0] de ruby.

    Nos testes de integração do Lettuce com Django[3], fiz testes funcionais casando 2 libs bem “mão na roda”: Django test client [1] e lxml.html [2].

    Mas como eu disse, foram só testes funcionais, que não conseguem processar javascript.

    O ideal seria ter algo como o Watir[0] pra python, ou seja, um driver jssh. Assim poderíamos rodar os testes em qualquer browser :)

    Links:

    [0] – http://watir.com/examples/
    [1] – http://docs.djangoproject.com/en/dev/topics/testing/#module-django.test.client
    [2] – http://codespeak.net/lxml/lxmlhtml.html#form-filling-example
    [3] – http://github.com/gabrielfalcao/lettuce/tree/master/tests/integration/alfaces/donothing/features/

  12. Samir Mamude disse:

    Olá Gabriel,

    Na verdade eu não preciso processar Javascript diretamente, pelo Selenium eu consigo acessar o DOM sem problemas, só que ele é meio bizarro de se trabalhar e entender :D

    Por isso perguntei se o Lettuce tem a capacidade de processar HTML como o Cucumber faz. Assim posso realizar chamadas POST|GET para testar o backend que roda sobre o Cyclone+MongoDB.

    Abs,
    Samir

  13. Gabriel Falcão disse:

    Hum… se só precisa processar o DOM, podes usar o lxml + client do Django. É bem divertido e fácil :)

  14. Max-B disse:

    I have to admit that follow this article was difficult (I officially know only Italian and English) but I do and enjoy!

    I hope this BDD framework has much follower since I like python and django very much and I think BDD is a great improvement in testing apps with customers.

    Thanks!

  15. [...] days after its first release candidate, lettuce is now much mature and also got new [...]

  16. [...] days after its first release candidate, lettuce is now much mature and also got new [...]

Leave a Response