Writing tests in python for beginners – Part 1 – doctest

So, I just started an interest on python tests and I would like to share what I learned so far.

Let’s skip all that theory about how tests are important for the code, bla bla bla, if you want to learn test, probably you already have your own reason, so, let’s jump to the part you actually write code!

Our application

Here a  simple code that calculates fibonacci. Let’s save it in the file fibonacci.py

def fibonacci(number):
    if number < 2:
        return number
    return fibonacci(number - 1) + fibonacci(number - 2)

So, as you can see, it’s a very simple code that calculates the fibonacci number, so, how can we ensure that this is working? Well, the easiest way is just invoke the code with different values, and check if the result will be the expected. So, in other words, you’re doing exactly what doctest intent to do!
so, probably you would write a python file, let’s say, test_fibonacci.py with the following content:

from fibonacci import fibonacci

def test_fibonacci():
    expected_result = [0, 1, 1, 2, 3, 5]
    for x in range(0, 5):
        result = fibonacci(x)
        if result != expected_result[x]:
            print "Failing on calculate fibonacci %s" % x

if __name__ == '__main__':
    print "Testing fibonacci"
    test_fibonacci()

Well, it might work, until you want to calculate fibonacci(200), then you gonna need to add a new list, alter the test code, etc.
What if we now only accept positive numbers and negative numberes throws an exception? Try/catch block? Well, soon you’re writing more code, and adding more complexity than you were expecting. Maybe you gonna need to test your test code itself to ensure that it’s working fine (are you feeling the inception here?)

Doctest

So, doctest can help you with some of these problems! Let’s see, first of all, you’re gonna need to create a simple txt file and add the following content:

>>> from fibonacci import fibonacci

>>> fibonacci(0)
0

>>> fibonacci(1)
1

>>> fibonacci(2)
1

>>> fibonacci(3)
2

>>> fibonacci(4)
3

>>> fibonacci(7)
12

So, basically, doctest expect every line starting with “>>>” to be a python code (we are importing fibonacci function in the line number 1 for example. And any other line as the result, looking just like the python shell.

Assuming that both fibonacci.py and fibonacci.txt are in the same directory, you can run the doctest with the command:

$ python -m doctest fibonacci.txt
**********************************************************************
File "fibonacci.txt", line 18, in fibonacci.txt
Failed example:
    fibonacci(7)
Expected:
    12
Got:
    13
**********************************************************************
1 items had failures:
   1 of   7 in fibonacci.txt
***Test Failed*** 1 failures.

Oops! Something went wrong! Don’t worry, that was expected. As you can see, the doctest shows a very good output when some error occurs, it shows you the line where the error happened, what was the expected result, and what was the result doctest gots. So, after fixing it, and runing again, we got no error

>>> from fibonacci import fibonacci

>>> fibonacci(0)
0

>>> fibonacci(1)
1

>>> fibonacci(2)
1

>>> fibonacci(3)
2

>>> fibonacci(4)
3

>>> fibonacci(7)
13
$ python -m doctest fibonacci.txt

Now let’s go further, and say: Hey, I don’t want negative numbers to be allowed, I want it to throw an exception. So, in this case, we just need to add a new like in our fibonacci.txt testing the fibonacci(-1) and of course, checking if the result will be an exception.
If we would do that in our test_fibonacci.py code, we should use a try/catch block, call the fibonacci(-1) inside it, and of course, this woudln’t be in the initial loop, and if something goes wrong, you wouldn’t have the cool output from doctest.

So, let’s change our fibonacci.py to not accept negative numbers:

def fibonacci(number):
    if number == 1 or number == 0:
        return number
    if number < 0:
        raise ValueError('Number is negative')
    return fibonacci(number - 1) + fibonacci(number - 2)

Even if we run our doctest after this changes, we got no error, but we are not testing the negative number yet. so, let’s add a fibonacci(-1) in our fibonacci.txt test.

Just a heads up, if we run fibonacci(-1) we will get a exception like this:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "fibonacci.py", line 5, in fibonacci
    raise ValueError('Number is negative')
ValueError: Number is negative

And you’re probably thinking that you can copy and paste this error on our fibonacci.txt and it will work, but  what if the file can change? You can add more code on the file, and the line where the error is being raised (in this case, line 5) might change. Being so, doctest only cares about the first and last lines, so our code in fibonacci.txt file will look like this:

>>> fibonacci(-1)
Traceback (most recent call last):
ValueError: Number is negative

And we are done! now we have a set of tests to our fibonacci code!

But what if you don’t want to have a txt and still have your tests? You can write doctest directly in your code on the docstring:

def fibonacci(number):
    '''
    This is a fibonacci function.
    Example of usage:
    >>> fibonacci(0)
    0
    >>> fibonacci(1)
    1
    >>> fibonacci(2)
    1
    >>> fibonacci(3)
    2
    >>> fibonacci(4)
    3
    >>> fibonacci(7)
    13
    >>> fibonacci(-1)
    Traceback (most recent call last):
    ValueError: Number is negative
    '''
    if number == 1 or number == 0:
        return number
    if number < 0:
        raise ValueError('Number is negative')
    return fibonacci(number - 1) + fibonacci(number - 2)

and you can run python -m doctest fibonacci.py.

More

Doctest have more features, as you can see below:

ELLIPISIS

According our fibonacci code, if you pass a negative number, it will raise a ValueError exception with the message ‘Number is negative’. There are some cases, that we don’t need to know which message is returning, we just want to know that an exception is being raised. Another example is when the output is the default __repr__ output, every time is a different memory address and you can’t control it. For this kind of situations, we can use the ELLIPISIS like in the example below.

>>> fibonacci(-1) #doctest: +ELLIPSIS
Traceback (most recent call last):
ValueError: ...

The line containing #doctest: + ELLIPSIS tells to doctest that the ‘…’ can match anything after ‘ValueError: ‘

SKIP

As the name says, it skips a test. This can be usefull when you know that some test is failing due some know bug, but it’s not fixed yet.

>>> fibonacci(-1) #doctest: +ELLIPSIS +SKIP
Traceback (most recent call last):
ValueError: ...

As you can see, you can use the two options, ELLIPSIS and SKIP together.

Conclusion

Tests can be fun and easy, and it helps to keep you code working properly in the whole cycle of development.
For more information about doctest, visit doctest website

C cedilha no Fedora 22

É sempre comum, após um upgrade termos o problema do ç aparecer como ć, para quem usa teclado padrão US. No Fedora 22 eu encontrei essa solução, que para mim foi muito mais simples do que ficar editando um monte de arquivo.

Lembrando que pode ser feito também no modo gráfico com as contra-partes (dconf-editor e im-chooser).

Instale os pacotes gtk3-immodules e gtk3-immodule-xim

sudo dnf install -y gtk3-immodules gtk3-immodule-xim

Alterar o input padrão:

imsettings-switch im-cedilla

Se por algum motivo você ver alguma mensagem desse tipo:

GDBus.Error:org.gtk.GDBus.UnmappedGError.Quark._imsettings_2derror_2dquark.Code5: Current desktop isn't targeted by IMSettings.

Por algum motivo, o gnome vem por padrão para não aceitar immodule do teclado, então, temos que alterar isso no dconf

dconf write /org/gnome/settings-daemon/plugins/keyboard/active false

Reinicie a sessão e seja feliz! Ou você pode sempre usar o Alt Gr + c e você terá o ç da mesma forma. É uma questão de se acostumar.

New small project: stackquery-dashboard

I’ve started a new project called stackquery-dashboard. Basically, it’s a web interface to show reports about user contribution in OpenStack, using the stackalytics.com API and part of the code from launchpadstats from  Martina Kollarova.

The first reason I start this project is because stackalytics.com only shows reports for each user, and sometimes managers in companies working with OpenStack, need a overview of all their employees at once, and it’s kinda boring to look for each user and then mount a spreadsheet.

The project have a Web interface, where you can create teams, assign users for these teams and generate reports based on several OpenStack projects (actually, right now it’s only Openstack and Stackforge).

The second reason is because for a long time I wanted to use Python for web, and it was a good opportunity to start.

Flask is really amazing and very easy to learn. I read this book and in one day I was already doing some cool stuff.
Also, since I’m not a Web designer, I had the opportunity to learn about Twitter bootstrap, which is very good for people who have no idea how CSS and JavaScript works and don’t want to waste a lot of time learning before start some project using these technologies.

The project is very simple, and still in the earlier stages. I’m not sure if it will be useful for anyone, but if is, please, let me know. I would be glad to hear about it.

Next steps
  • I need to work on the unit tests (yes, I started the project before create the unit tests, but I’ll fix it soon)
  • Documentation
  • More API’s
  • More types of reports
  • Make the project work with modules so you can have modules enabled for other types of reports
  • Create a config file
  • Save the state in the forms between posts
  • Better message system when delete, update and create teams, users, projects, etc.
  • Can’t think anything else for now.

And if you’re interested, here’s a few screenshots:

Screen Shot 2015-02-05 at 10.56.10 Screen Shot 2015-02-05 at 10.56.17 Screen Shot 2015-02-05 at 10.56.25 Screen Shot 2015-02-05 at 10.56.39 Screen Shot 2015-02-05 at 10.57.08

Zenity is not dead!

First of all, it’s been a while since my last update in this blog, and I will start to write more about all the stuff that I’m doing (right now I’m working a lot with openstack, so be ready for posts about it).

Now let’s go for what matter: Zenity is not dead! I just don’t have enough time to work alone in all 2008-2012 bugs still opened there, but I’m doing what I can, and here’ s the news:

This bug  from 2012 is finally fixed! Seriously, this was my nightmare for a long time, until I found this!.

So, the old behavior:

zenity --warning --text='A b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v'

Then you get this crappy and ugly thing:

Old behaviour

And this happened because GtkLabel normally allocate enough space when you try to resize the window, like this:

Zenity resize

Now you can have the very expected behaviour:

zenity --warning --text='A b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v'

New and expected behaviour

And if you have a huge text and want to resize your window, now you have an –ellipsize option too!!!

zenity --warning --text='A b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v' --ellipsize

Ellipsize behaviour

See the “…” in the middle? That’s what I’m talking about!

So, here’ s what I’m planning to do:

  • Remove all old and deprecated gtk_ calls replacing for the new ones.
  • Add a dialog with several button options (cool huh? I know people are asking for this).
  • Fix several bugs that’s still opened.
  • Launch new versions of zenity often, so distro maintainers can have more work to do :D.

And that’s it for now guys! Zenity is a great project, abandoned but, a great project, and needs all your love. So, if you’re interested, open bugs, send patches, help the project!

New –forms option for zenity

This looks good! I know it need’s a little bit more work on the interface but it looks very promising.
I’ve been working on zenity to add a new –forms option based on bug #412493 requested by @aurium, and I believe it’s getting pretty good!
Right now I have –add-entry, –add-password and –add-calendar option. I need to work more in the calendar layout.
You can check the new option in the screenshot bellow:

Zenity with --forms option
zenity --forms option in action

If you have any ideas for this new option, feel free to post in comments 🙂

Como gerar um patch usando o git

Você quer ajudar no desenvolvimento do seu aplicativo predileto, e não sabe usar o git, ou como gerar um patch com ele? Eis aqui uma pequena receita de bolo:

1 – Baixe o aplicativo do repositório git com o seguinte comando:

git clone git://repositorio.do.aplicativo.git

2 – Suponhamos que você quer criar um patch para ser enviado aos mantenedores do aplicativo em questão, qual a melhor maneira de fazer isso? Na minha opnião é criando um branch para o seu patch com o seguinte comando:

git checkout -b bug_xxxx_exemplo_de_branch

Pronto! Você criou um novo branch, e está pronto para programar!

3 – Programe!

Agora digamos que você fez várias alterações no código, está na hora de gerar o patch. Antes de mais nada, você precisa adicionar no git as alterações. Então digamos que você modificou o arquivo aplicativo.c e adicionou o arquivo novo_arquivo.c no seu patch, utilize o seguinte comando:

git add aplicativo.c novo_arquivo.c

Claro que você pode usar o git add para cada arquivo que você adicionar também.

Feito isso, vamos comitar essas alterações. Note que o commit nesse caso, não signfica que você estará subindo as alterações que você fez para o repositório git ainda (até porque talvez você não tenha permissão para isso). O commit é apenas para confirmar que você realmente terminou o que estava fazendo e está pronto para gerar o patch.

git commit

Vai aparecer um editor de textos, pedindo para você colocar as notas a respeito do patch. Salve tudo, e pronto! falta só um pouquinho para que você gere o patch, e isso você faz da seguinte maneira:

git format-patch master --stdout > meu_primeiro.patch

E pronto! Um patch novinho em folha para você enviar para o mantenedor do seu aplicativo preferido! E o melhor de tudo, ele só vai precisar executar um único comando para aplicar seu patch.

Antes que eu me esqueça, fez algo que se arrependeu?

git reset HEADˆ

ou

git reset --hard HEAD^

Maré de azar?

Semana santa acabei viajando para a Bahia, e fui passar o fim de semana com meus pais no interior, onde estava rolando uma festa chamada Feira dos caxixis. É uma festa bem antiga, que ocorre há mais de 100 anos na cidade.

Enfim, estava eu lá usando meu macbook, e minha irmã usando o hp dela, quando de repente, os dois param de funcionar. Achei estranho pois não houve nenhuma queda de energia, e mesmo que tivesse, eram para os computadores continuarem ligados, pois havia carga na bateria.

Tentamos sem sucesso religar os computadores, mas nada acontecia. Foi quando nos veio a notícia que houve uma sobrecarga na rede elétrica.

Resultado: o HP teve um prejuízo de no mínimo (pois minha irmã ligou para a assistência técnica e disse o que havia acontecido e o cara disse que provavelmente seria isso) 450 reais para trocar uma placa que conecta a placa de vídeo ao motherboard, enquanto o macbook vai custar 640 reais em uma bateria nova e mais 370 reais na controladora de energia que aparentemente está com defeito.

Estamos tentando junto à Coelba, ver se eles vão ressarcir as nossas perdas, porém eles estão pedindo tanta coisa (nota fiscal do computador, o qual não lembro onde está, número de série, dia que comprou, identidade, cpf etc, etc, etc, que aparentemente é para que acabemos desistindo, ou que demore tanto que quando recebermos um notebook novo ou o nosso consertado, não tenha mais graça.

Acho que no final das contas, vamos ter que ir ao PROCON…

E ai vai começar mais uma luta…

Enquanto isso, só posso falar com minha irmã por telefone, ou por sms, encarecendo a minha conta telefonica, e ainda vou ter que gastar uma nota enviando meu macbook para a Bahia só para a Coelba dizer que ela não tem culpa nenhuma do que aconteceu (elas nunca tem culpa, apenas a gente que usou de maneira indevida colocando pra carregar na tomada)

Alguns updates

Longo, longo tempo sem postar nada, então vamos a alguns updates que aconteceram na minha vida:

Não moro mais em Salvador, estou morando em Campinas, surgiu uma oportunidade de eu vir para São Paulo para trabalhar na IBM e acabei vindo. Aqui trabalho como analista na área de .Net (é eu sei, .Net… seria mais legal se fosse mono hein 😉 ).

Já estou aqui há 5 meses, estou gostando muito da cidade e da empresa. Só não é muito bom as pessoas de Campinas, que não tem o calor do povo baiano, de conversar, sair juntos, curtir, essas coisas, e essa cultura é bem estranha para mim ainda, mas a gente vai se acostumando, ou melhor, aceitando, pois acostumar eu nunca irei 🙂

Quero voltar a programar pra linux, estou tentando ajudar o Pedro Castro em umas loucuras que estamos querendo implementar no Gnome-Subtitles (vai ficar show se conseguirmos) e mais uma vez, aviso: precisamos de mais colaboradores para o GS, logo se você for um entusiasta do Gnome e curte editar legendas, e tem skills em programação em mono e gtk, eis a sua chance, se não, manda uns emails com idéias que também são bem vindas 🙂

Também estou estudando objective-c para fazer algumas coisas no mac, mas ainda estou devagar nisso, porém pretendo levar adiante.

Ah, e depois de ler os reviews do rodrigo toledo sobre o N810 e saber que o ubuntu foi portado para ele, estou cada vez mais com vontade de ter um treco desses. Às vezes é mais legal ter um tablet desses (pena que ainda não achei no Brasil fora o mercado livre, só o N800) do que ter um Netbook, ou notebook. Normalmente fico com preguiça de ligar meu notebook, e só uso o desktop porque ele já fica ligado o tempo todo.

Então é isso, breve voltarei com coisas mais técnicas, e vou criar outro blog só para tratar das minhas coisas pessoais que não tem nada a ver com o mundo do software livre ou tecnologia.

Gnome-subtitles need’s love!

Ok, a brand new ubuntu version is coming, and me and Pedro is having trouble to talk with debian mono team to create packages for the new version of gnome-subtitles, since now the sublib is separated from the gnome-subtitles (as a package too) and the old maintainer Tiago Vaz, is kinda busy to still work with gnome-subtitles.

So, if you have experience in .deb packages and want to help this greate gnome app, there’s your chance!