Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Qualidade levada a sério em Python - Emilio Simoni

208 views

Published on

Python é uma das mais poderosas ferramentas de prototipação e analise de hipóteses. Mas o que muitos não sabem, é que também podemos ter produtos completos em produção totalmente baseados em Python. Ai vem a pergunta, como garantir a qualidade e eficiência do meu projeto em Python ???
Venha descobrir como aplicar e garantir a qualidade dos seus projetos através de testes eficientes, checagem de cobertura de código, analise estática, índice de mantenabilidade dentre outras técnicas.

Published in: Software
  • Be the first to comment

Qualidade levada a sério em Python - Emilio Simoni

  1. 1. simple is better than complex The Zen of Python (import this) Qualidade levada a sério em Python
  2. 2. • Master Coaching Trainer • Pesquisador de segurança sênior • Programador C/C++ e Python • Data Scientist • Viciado em competições de ML • Coordenador equipe ameaças PSafe
  3. 3. 5° software mais baixado Maior empresa mobile LA 200 mil downloads/dia
  4. 4. Pessoas Processo Produto
  5. 5. Versionamento Qualidade Automatização Requisitos Metodologia Processo = Engenharia de software
  6. 6. Testes Analise estática Bug Tracking Documentação
  7. 7. Testes de software
  8. 8. Específicos Auto descritivos Auto suficientes Indicar o comportamento esperado Servir de documentação Bugs tendem a virar um caso de teste Unit Tests
  9. 9. PyUnit Unit Tests assertTrue assertEqual assertAlmostEqual assertIn
  10. 10. Mão na massa!
  11. 11. Test Fixture Test Case Test Suite Test Runner Unit Tests
  12. 12. Test Fixture
  13. 13. Test Fixture class SimpleTestCase(unittest.TestCase): def setUp(self): """Call before every test case.""“ self.foo = Foo() self.file = open( "blah", "r" ) def tearDown(self): """Call after every test case.""“ self.file.close()
  14. 14. OQueTaSendoTestando_Parametros_RetornoEsperado get_client_name__with_invalid__params_must_return_False Test Case
  15. 15. def test_get_client_name__with_invalid__params_must_return_False (self): """Test case 1. note that all test method names must begin with 'test.'""“ self.assertEqual(foo.get_client_name(None) , False) OQueTaSendoTestando_Parametros_RetornoEsperado get_client_name__with_invalid__params_must_return_False
  16. 16. import unittest from foobarbaz import Foo # code from module you're testing class SimpleTestCase(unittest.TestCase): def setUp(self): """Call before every test case.""“ self.foo = Foo() self.file = open( "blah", "r" ) def tearDown(self): """Call after every test case.""“ self.file.close() def test_get_client_name__with_invalid__params_must_return_False (self): """Test case 1. note that all test method names must begin with 'test.'""“ self.assertEqual(foo.get_client_name(None) , False) Test Suite
  17. 17. Gerencia os testes e fornece uma interface de acesso. Test Runner
  18. 18. Teste se torna o primeiro cliente do seu código Somente o codigo necessario é criado Erros são identificados mais rapidamente Ganho de produtividade Códigos entregues realmente prontos Facilita depuração
  19. 19. Integration Tests
  20. 20. Integration Tests def test_add_source_must_check_duplicated(self): psw = PhishingServiceWrapper() psw.add_url('http://www.testededominio.com.br', source_id=1) add_ret = psw.add_url('http://www.testededominio.com.br', source_id=1) self.assertEqual(add_ret['status'], 'duplicated')
  21. 21. Performance Tests
  22. 22. Performance Tests __main__.SomeTest.testOne: 1.001 __main__.SomeTest.testTwo: 2.002 ----------------------------------------------- Ran 2 tests in 3.003s OK
  23. 23. Performance Tests import cProfile import unittest if __name__ == '__main__': suite = unittest.TestLoader().discover('.') def runtests(): unittest.TextTestRunner().run(suite) cProfile.run('runtests()',sort='cumtime')
  24. 24. Performance Tests 25510 function calls (25298 primitive calls) in 0.820 seconds Ordered by: cumulative time ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.820 0.820 <string>:1(<module>)
  25. 25. Performance Tests def test_add_source_must_check_duplicated(self): import time psw = PhishingServiceWrapper() before_functiion = time.time() psw.add_url('http://www.testededominio.com.br', source_id=1) after_functiion = time.time() self.assertLess(after_functiion - before_function, 1.0)
  26. 26. Performance Tests@profile def primes(n): if n==2: return [2] elif n<2: return [] s=range(3,n+1,2) mroot = n ** 0.5 half=(n+1)/2-1 i=0 m=3 while m <= mroot: if s[i]: j=(m*m-3)/2 s[j]=0 while j<half: s[j]=0 j+=m i=i+1 m=2*i+3 return [2]+[x for x in s if x] primes(100) pip install line_profiler kernprof -l –v primes.py
  27. 27. Performance Tests Line # Hits Time Per Hit % Time Line Contents ============================================================== 2 @profile 3 def primes(n): 4 1 2 2.0 1.1 if n==2: 5 return [2] 6 1 1 1.0 0.5 elif n<2: 7 return [] 8 1 4 4.0 2.1 s=range(3,n+1,2) 9 1 10 10.0 5.3 mroot = n ** 0.5 10 1 2 2.0 1.1 half=(n+1)/2-1 11 1 1 1.0 0.5 i=0 12 1 1 1.0 0.5 m=3 13 5 7 1.4 3.7 while m <= mroot: 14 4 4 1.0 2.1 if s[i]: 15 3 4 1.3 2.1 j=(m*m-3)/2 16 3 4 1.3 2.1 s[j]=0 17 31 31 1.0 16.3 while j<half: 18 28 28 1.0 14.7 s[j]=0 19 28 29 1.0 15.3 j+=m 20 4 4 1.0 2.1 i=i+1 21 4 4 1.0 2.1 m=2*i+3 22 50 54 1.1 28.4 return [2]+[x for x in s if x]
  28. 28. Performance Tests python -m memory_profiler primes.py pip install memory_profiler
  29. 29. Performance 2 @profile 3 7.9219 MB 0.0000 MB def primes(n): 4 7.9219 MB 0.0000 MB if n==2: 5 return [2] 6 7.9219 MB 0.0000 MB elif n<2: 7 return [] 8 7.9219 MB 0.0000 MB s=range(3,n+1,2) 9 7.9258 MB 0.0039 MB mroot = n ** 0.5 10 7.9258 MB 0.0000 MB half=(n+1)/2-1 11 7.9258 MB 0.0000 MB i=0 12 7.9258 MB 0.0000 MB m=3 13 7.9297 MB 0.0039 MB while m <= mroot: 14 7.9297 MB 0.0000 MB if s[i]: 15 7.9297 MB 0.0000 MB j=(m*m-3)/2 16 7.9258 MB -0.0039 MB s[j]=0 17 7.9297 MB 0.0039 MB while j<half: 18 7.9297 MB 0.0000 MB s[j]=0 19 7.9297 MB 0.0000 MB j+=m 20 7.9297 MB 0.0000 MB i=i+1 21 7.9297 MB 0.0000 MB m=2*i+3 22 7.9297 MB 0.0000 MB return [2]+[x for x in s if x]
  30. 30. Bug Tracking
  31. 31. Bug Tracking import unittest from foobarbaz import Foo class SimpleTestCase(unittest.TestCase): def setUp(self): """Call before every test case.""“ self.foo = Foo() self.file = open( "blah", "r" ) def tearDown(self): """Call after every test case.""“ self.file.close() def test_get_client_name__with_big_param__must_return_False (self): self.assertEqual(foo.get_client_name(“A” * 1024*1024) , False)
  32. 32. Analise estática
  33. 33. Analise estática Checar idioma Documentação de codigo Compliance Erros Codigos duplicados ou complexos pylint file.py pip install pylint
  34. 34. Analise estática
  35. 35. Analise estática radon pip install radon Complexidade ciclomática Linhas de código, comentários, ... Maintainability Index
  36. 36. Analise estática
  37. 37. Analise estática
  38. 38. Analise estática
  39. 39. Analise estática
  40. 40. Documentação DocStrings Documentação simples e clara, não deve conter detalhes da implementação Documentação ruim é pior do que não documentado Sumarizar o comportamento da função Argumentos, retornos, exceções disparadas e restrições. Não documentar o obvio
  41. 41. Documentação
  42. 42. import this simple is better than complex
  43. 43. pep-0020 The Zen of Python
  44. 44. Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!
  45. 45. emiliocini@gmail.com www.emiliosimoni.com

×