qualidade levada a sério em python - emilio simoni

Post on 21-Jan-2017

147 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

simple is better than complexThe Zen of Python (import this)

Qualidade levada a sério em Python

• 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

5° software mais baixadoMaior empresa mobile LA200 mil downloads/dia

PessoasProcesso

Produto

Versionamento

QualidadeAutomatização

RequisitosMetodologia

Processo = Engenharia de software

Testes

Analise estática

Bug Tracking

Documentação

Teste

s au

tom

atiza

dos

Testes de software

Específicos

Auto descritivos

Auto suficientes

Indicar o comportamento esperado

Servir de documentação

Bugs tendem a virar um caso de teste

Unit Tests

PyUnit

Unit Tests

assertTrue

assertEqual

assertAlmostEqual

assertIn

Mão na massa!

Test Fixture

Test Case

Test Suite

Test Runner

Unit Tests

Test Fixture

Test Fixtureclass 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()

OQueTaSendoTestando_Parametros_RetornoEsperadoget_client_name__with_invalid__params_must_return_False

Test Case

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_RetornoEsperadoget_client_name__with_invalid__params_must_return_False

import unittestfrom 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

Gerencia os testes e fornece uma interface de acesso.

Test Runner

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

Integration Tests

Integration Testsdef 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')

Performance Tests

Performance Tests

__main__.SomeTest.testOne: 1.001 __main__.SomeTest.testTwo: 2.002 -----------------------------------------------

Ran 2 tests in 3.003s OK

Performance Testsimport cProfileimport unittest if __name__ == '__main__':   suite = unittest.TestLoader().discover('.')   def runtests():      unittest.TextTestRunner().run(suite)   cProfile.run('runtests()',sort='cumtime')

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>)

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)

Performance Tests@profiledef 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

Performance TestsLine # 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]

Performance Tests

python -m memory_profiler primes.py

pip install memory_profiler

Performance2 @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]

Bug Tracking

Bug Trackingimport unittestfrom 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)

Analise estática

Analise estáticaChecar idioma

Documentação de codigo

Compliance

Erros

Codigos duplicados ou complexos

pylint file.py

pip install pylint

Analise estática

Analise estática

radonpip install radon

Complexidade ciclomática

Linhas de código, comentários, ...

Maintainability Index

Analise estática

Analise estática

Analise estática

Analise estática

DocumentaçãoDocStrings

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

Documentação

import thissimple is better than complex

pep-0020The Zen of Python

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!

emiliocini@gmail.comwww.emiliosimoni.com

top related