SlideShare ist ein Scribd-Unternehmen logo
1 von 67
Pruebas Unitarias con Django
Tomás Henríquez   tchenriquez@gmail.com
2-11-2012
Historia de las pruebas
                             en el software

http://clearspecs.com/joomla15/downloads/ClearSpecs16V01_GrowthOfSoftwareTest.pdf
Historia de las pruebas



Período orientado al Debugging
        (antes - 1956)
Historia de las pruebas



Período orientado a la demostación
          (1957 - 1978)
Historia de las pruebas
Historia de las pruebas



Período orientado a la destrucción
          (1979 - 1982)
Historia de las pruebas



Período orientado a la evaluación
         (1983 - 1987)
Historia de las pruebas


“Ninguna técnica puede garantizar software
   sin errores, sin embargo, un conjunto de
 técnicas cuidadosamente elegidas para un
    proyecto en específico puede ayudar a
  asegurar el desarrollo y mantenimiento de
    software de calidad para un proyecto”
Historia de las pruebas



Período orientado a la prevención
          (1988 - Hoy)
Pruebas Unitarias
Pruebas



¿Cómo uno usualmente prueba
        su código?
Pruebas



¿Qué problemas tiene
   el debugging?
Pruebas



¿Cómo persistir
estas pruebas?
Pruebas
¡NO ES FÁCIL!
Pruebas
                    ¡NO ES FÁCIL!

●   Carga de datos para la prueba
●   No debe afectar la base de datos
●   Super rápidas
Sheet Got Serious
Carga de datos


 FIXTURES
Carga de datos


class Profession(models.Model):
    name = models.CharField(max_length=30, unique=True)
    specialist = models.CharField(max_length=30, blank=True)
Carga de datos
[
      {
     "pk": 1,
           "model": "my_app.profession",
           "fields": {
               "name": "panadero",
               "specialist": "pizza",
           }
      },
      {
           "pk": 2,
           "model": "my_app.profession",
           "fields": {
               "name": "forever_alone",
               ...
 ]
Carga de datos


class Profession(models.Model):
    name = models.CharField(max_length=30, unique=True)
    specialist = models.CharField(max_length=30, blank=True)
    full_time = models.BooleanField(default=False)   <----
Carga de datos
[
      {
     "pk": 1,
           "model": "my_app.profession",
           "fields": {
               "name": "panadero",
               "specialist": "pizza",
               "full_time": false,   <--- Ay no.....
           }
      },
      {
           "pk": 2,
           "model": "my_app.profession",
           "fields": {
               "name": "forever_alone",
               ...
 ]
Carga de datos
[
      {
     "pk": 1,
           "model": "my_app.profession",
           "fields": {
               "name": "panadero",
               "specialist": "pizza",
               "full_time": false,   <--- Ay no.....
           }
      },
      {
           "pk": 2,
           "model": "my_app.profession",
           "fields": {
               "name": "forever_alone",
               ...
 ]
Carga de datos


      FIXTURES
¿Para qué son buenos?
Carga de datos
               Estructura del App
my_app/
    __init__.py
    models.py
    fixtures/base.json <------
    tests.py
Carga de datos
class UserTest(TestCase):
    fixtures = ['base.json']

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_coolness(self):
        # usuario con id == 1 existe gracias al fixture

        user = User.objects.get(id=1)

       self.assertTrue(user.is_cool, False)
       user.become_a_hipster()
       self.assertTrue(user.is_cool, True)
Carga de datos


           Factories

https://github.com/dnerdy/factory_boy
Carga de datos


           Factories
●
    Organizado    <------
Carga de datos
from django.db import models

class Receipt(models.Model):
    user_id = fields.IntegerField()
    merchant = fields.CharField(max_length=30)

class ReceiptItem(models.Model):
    name = models.CharField(max_length=30)
    quantity = models.IntegerField(default=1)
    alert_sent = models.BooleanField(default=False)
    receipt = models.ForeignKey(Receipt)

class Attach(models.Model):
    name = models.CharField(max_length=30)
    item = models.ForeignKey(ReceiptItem)
Carga de datos
class ReceiptTest(TestCase):
    fixtures = ['base.json']

   def setUp(self):
       rep = Receipt(user_id=1, merchant='mami')
       rep.save()

       ri = ReceiptItem(name='medias', quantity=2,
                receipt=rep)
       ri.save()

       att = Attach(name='foto_de_juanita.jpg', item=ri)
       att.save()
       ...
Carga de datos
class ReceiptTest(TestCase):
    fixtures = ['base.json']

   def setUp(self):
       rep = Receipt(user_id=1, merchant='mami')
       rep.save()

       ri = ReceiptItem(name='medias', quantity=2)
       ri.save()

       att = Attach(name='foto_de_juanita.jpg', item=ri)
       att.save()
       ...
Carga de datos
               Estructura del App
my_app/
    __init__.py
    models.py
    fixtures/base.json
    factories.py <-------
    tests.py
Carga de datos
class ReceiptFactory(factory.Factory):
    FACTORY_FOR = Receipt

    user_id = 1
    merchant = "mami"

class ReceiptItemFactory(factory.Factory):
    FACTORY_FOR = ReceiptItem

    name = factory.Sequence(lambda n: 'item-%s' % n)
    quantity = 1
    receipt = ReceiptFactory()

class AttachmentFactory(factory.Factory):
    FACTORY_FOR = Attachment

    name = factory.Sequence(lambda n: 'attachment-%s' % n)
    item = ReceiptItemFactory()
Carga de datos
class ReceiptTest(TestCase):
    fixtures = ['base.json']

   def setUp(self):

       ReceiptFactory()
       ...
Carga de datos
Carga de datos
Carga de datos
Carga de datos


           Factories
●
    Organizado
●
    Flexible     <-------
Carga de datos
class ReceiptTest(TestCase):
    fixtures = ['base.json']

   def setUp(self):
       # No se crea en base de datos
       ReceiptFactory.build()
       ...
Carga de datos
class ReceiptTest(TestCase):
    fixtures = ['base.json']

   def setUp(self):
       # Crear muchos objects
       ReceiptFactory.create_batch(5)
       ...
Carga de datos


            Factories
●
    Organizado
●
    Flexible
●
    Facil de migrar
    <-------
Carga de datos
from mongoengine.document import Document, EmbeddedDocument

class Attach(EmbeddedDocument):
    name = fields.StringField(required=True)

class ReceiptItem(EmbeddedDocument):
    name = fields.StringField(required=True)
    quantity = fields.DecimalField(default=Decimal(1))
    alert_sent = fields.BooleanField(default=False)
    attachments = fields.ListField(fields.EmbeddedDocumentField(Attach))

class Receipt(Document):
    user_id = fields.IntField(required=True)
    merchant = fields.StringField(required=True)

    items = fields.ListField(fields.EmbeddedDocumentField(ReceiptItem))
Carga de datos
class AttachmentFactory(factory.Factory):
    FACTORY_FOR = Attachment

    name = factory.Sequence(lambda n: 'attachment-%s' % n)

class ReceiptItemFactory(factory.Factory):
    FACTORY_FOR = ReceiptItem

    name = factory.Sequence(lambda n: 'item-%s' % n)
    quantity = 1
    Attachments = [AttachmentFactory.build()]

class ReceiptFactory(factory.Factory):
    FACTORY_FOR = Receipt

    user_id = 2
    merchant = "Amazon"
    items = [ReceiptItemFactory.build()]
Carga de datos
class ReceiptTest(TestCase):
    fixtures = ['base.json']

   def setUp(self):

       ReceiptFactory()
       ...
MOCKERS

         http://labix.org/mocker
http://www.voidspace.org.uk/python/mock/
Mockers
Mockers
def tweet(tokens, body):
    consumer = oauth.Consumer(TWITTER_KEY,
            settings.TWITTER_SECRET)
    token = oauth.Token(tokens.oauth,
                tokens.oauth_secret)
    client = oauth.Client(consumer, token)

   header, body = client.request("http://api.twitter.com/1/statuses/"
           "update.json", "POST", body="status=%s" % body)

   if header['status'] == '401':
       return False, ('Twitter account not authorized.'
                       ' Please connect your account again.')

   body = json.loads(body)
   if header['status'] != '200':
       return False, body.get('error', 'Unknown Twitter error')
   return True, sbody['id_str']
Mockers
from mocker import Mocker, ARGS, KWARGS

class TweetTest(TestCase):
    fixtures = ['base.json']

    def setUp(self):
        mocker = Mocker()
        mock_client = mocker.replace('oauth.Client')
        mock_client.request(ARGS, KWARGS)
        mocker.response({'code': 200,
            'text': 'OK', 'description': 'Success!'}) <----
        self.mocker = mocker

    def test_tweet(self):
        user = User.objects.get(id=1)
        self.assertTrue(user.tweets, 0)

        with self.mocker:
            res = tweet(user.tokens,
               'esto es un Tweet de prueba')

        self.assertEquals(res, True)
Mockers
from mocker import Mocker, ARGS, KWARGS

class TweetTest(TestCase):
    fixtures = ['base.json']

   def setUp(self):
       mocker = Mocker()
       mock_client = mocker.replace('oauth.Client')
       mock_client.request(ARGS, KWARGS)
       mocker.throw(ConnectionException)   <----
       self.mocker = mocker

   def test_tweet(self):
       user = User.objects.get(id=1)

        # Podemos manejar la excepcion?
        with self.mocker:
            tweet(user.tokens,
               'esto es un Tweet de prueba')
Buenas y Malas
   Practicas
Tips

¿Hacer Pruebas antes de lanzar código?
Tips
                          MAL
def test_gmail(self):
    expected_msg = {
        'subject': 'SeamlessWeb Order',
        'plain': '[image: Seamless Web Logo] ...' # MAL
        'html': 'n<table width="640" border=...' # MAL
    }
    m = Message.objects.get(pk=1)
    msg = {
        'subject': m.subject,
        'html': m.body_mimetype_html,
        'plain': m.body_mimetype_plain
    }

    msg = strip_forwarding(msg)

    self.assertEqual(msg['subject'], expected_msg['subject'])
    self.assertEqual(msg['plain'], expected_msg['plain'])
    self.assertEqual(msg['html'], expected_msg['html'])
Tips
                           BIEN
def test_gmail(self):
    strips = ('---------- Forwarded message ----------',
            'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ')
    checks = {'subject': u'SeamlessWeb Order'}

    msg = strip_forwarding(msg)

    # Validar que los valores sean los esperados
    for key, val in checks.items():
        self.assertEqual(val, msg[key])

    # Asegurar que estos valores no se encuentren en el email
    for strip in strips:
        for m in msg.values():
            self.assertNotIn(strip, m)
Tips

No hacer multiples pruebas en una función
Tips
                            MAL
def test_emails(self):
    strips = ('---------- Forwarded message ----------',
            'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ')
    checks = {'subject': u'SeamlessWeb Order'}

    gmail, aol, hotmail = message.objects.all()[:2]
    msgs = (strip_forwarding(gmail),
        strip_forwarding(aol), strip_forwarding(hotmail))

    for msg in msgs:
        for key, val in checks.items():
            self.assertEqual(val, msg[key])

        for strip in strips:
            for m in msg.values():
                self.assertNotIn(strip, m)
Tips
                           BIEN
def test_gmail(self):
    strips = ('---------- Forwarded message ----------',
            'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ')
    checks = {'subject': u'SeamlessWeb Order'}

    gmail = message.objects.get(id=1)
    msgs = strip_forwarding(gmail)
    for key, val in checks.items():
        self.assertEqual(val, msg[key])

    for strip in strips:
        for m in msg.values():
            self.assertNotIn(strip, m)

def test_aol(self):
    strips = ('---------- Forwarded message ----------',...
Tips
                           BIEN
def test_gmail(self):
    strips = ('---------- Forwarded message ----------',
            'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ')
    checks = {'subject': u'SeamlessWeb Order'}

    gmail = message.objects.get(id=1)
    msgs = strip_forwarding(gmail)
    for key, val in checks.items():
        self.assertEqual(val, msg[key])

    for strip in strips:
        for m in msg.values():
            self.assertNotIn(strip, m)

def test_aol(self):
    strips = ('---------- Forwarded message ----------',...
Tips
                 Pruebas por Aserción
def test_gmail_checks(self):
    checks = {'subject': u'SeamlessWeb Order'}

    gmail = message.objects.get(id=1)
    msgs = strip_forwarding(gmail)
    for key, val in checks.items():
        self.assertEqual(val, msg[key])   <---- Asercion

def test_gmail_strips(self):
    strips = ('---------- Forwarded message ----------',
            'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ')

    gmail = message.objects.get(id=1)
    msgs = strip_forwarding(gmail)
    for strip in strips:
        for m in msg.values():
            self.assertNotIn(strip, m)     <---- Asercion
Tips
                  Pruebas por Acción
def test_gmail(self):
    strips = ('---------- Forwarded message ----------',
            'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ')
    checks = {'subject': u'SeamlessWeb Order'}

    gmail = message.objects.get(id=1)

    msgs = strip_forwarding(gmail)   <---- ACCION

    for key, val in checks.items():
        self.assertEqual(val, msg[key])

    for strip in strips:
        for m in msg.values():
            self.assertNotIn(strip, m)
Tips
             Probar todas las ramas
def handle_coolness(self, user):
    if user.is_cool:
        do_cool_stuff(user)
    else:
        raise NotCoolDudeException
Pruebas de Integración
Pruebas de Integración
                 django client library
def test_view(self):
    user = User.objects.get(id=1)
    url = '/login/'

   response = self.client.post(url, {
       'username': user.username,
       'password': 'fakybaby',
       'timezone': 'America/Caracas'
   }

   self.assertEquals(response.status_code, 200)
   self.assertEquals(response.cookies_set['logged_name'], 
      User.username)
Pruebas de Integración
                 django client library
def test_view(self):
    user = User.objects.get(id=1)
    url = '/login/'

   response = self.client.post(url, {
       'username': user.username,
       'password': 'fakybaby',
       'timezone': 'America/Caracas'
   }

   self.assertEquals(response.status_code, 200)
   self.assertEquals(response.cookies_set['logged_name'], 
      User.username)
Pruebas de Integración
                        WebTest!
def test_view(self):
    user = User.objects.get(id=1)
    url = '/login/'

   form = self.app.get(url).forms['login-form']
   form['username'] = user.username
   form['password'] = 'fakybaby'
   response = form.submit().follow()

   self.assertEquals(response.status_code, 200)
   self.assertEquals(response.cookies_set['logged_name'], 
       user.username)
Continuous deployment

    http://jenkins-ci.org/
Continuous Deployment
     Integrado por django_jenkins
       Correr Pruebas unitarias
Verificacion de codigo (Pep8, jslint, etc)
                Reportes
                 Emails
Continuous Deployment

if len(sys.argv) > 1 and sys.argv[1] in ['test', 'jenkins']:
    # test mongo db
    MONGO_DBNAME = 'db_test'
    db = mongoengine.connect(MONGO_DBNAME,
            username=MONGO_USERNAME,
            password=MONGO_PASSWORD,
            host=MONGO_HOST,
            port=MONGO_PORT, safe=True)
    db.drop_database(MONGO_DBNAME) # drop entire database
¿Preguntas?

@hazuek
tchenriquez@gmail.com
github.com/hassek

Weitere ähnliche Inhalte

Was ist angesagt?

Changepoint Detection with Bayesian Inference
Changepoint Detection with Bayesian InferenceChangepoint Detection with Bayesian Inference
Changepoint Detection with Bayesian InferenceFrank Kelly
 
Pertemuan 1 Konsep Dasar Testing
Pertemuan 1 Konsep Dasar TestingPertemuan 1 Konsep Dasar Testing
Pertemuan 1 Konsep Dasar TestingEndang Retnoningsih
 
Test Cases Maintaining & Documenting
Test Cases Maintaining & DocumentingTest Cases Maintaining & Documenting
Test Cases Maintaining & DocumentingSeyed Ali Marjaie
 
Double Loop: TDD & BDD Done Right
Double Loop: TDD & BDD Done RightDouble Loop: TDD & BDD Done Right
Double Loop: TDD & BDD Done RightJessica Mauerhan
 
Code Smells and Its type (With Example)
Code Smells and Its type (With Example)Code Smells and Its type (With Example)
Code Smells and Its type (With Example)Anshul Vinayak
 
Winning data science competitions, presented by Owen Zhang
Winning data science competitions, presented by Owen ZhangWinning data science competitions, presented by Owen Zhang
Winning data science competitions, presented by Owen ZhangVivian S. Zhang
 
Practical learnings from running thousands of Flink jobs
Practical learnings from running thousands of Flink jobsPractical learnings from running thousands of Flink jobs
Practical learnings from running thousands of Flink jobsFlink Forward
 
CNIT 127: Ch 18: Source Code Auditing
CNIT 127: Ch 18: Source Code AuditingCNIT 127: Ch 18: Source Code Auditing
CNIT 127: Ch 18: Source Code AuditingSam Bowne
 
Toi uu hoa he thong 30 trieu nguoi dung
Toi uu hoa he thong 30 trieu nguoi dungToi uu hoa he thong 30 trieu nguoi dung
Toi uu hoa he thong 30 trieu nguoi dungIT Expert Club
 
Software Testing Basics
Software Testing BasicsSoftware Testing Basics
Software Testing BasicsBelal Raslan
 
Resilient service to-service calls in a post-Hystrix world
Resilient service to-service calls in a post-Hystrix worldResilient service to-service calls in a post-Hystrix world
Resilient service to-service calls in a post-Hystrix worldRares Musina
 
Equivalence partitions analysis
Equivalence partitions analysisEquivalence partitions analysis
Equivalence partitions analysisVadym Muliavka
 
Advanced pg_stat_statements: Filtering, Regression Testing & more
Advanced pg_stat_statements: Filtering, Regression Testing & moreAdvanced pg_stat_statements: Filtering, Regression Testing & more
Advanced pg_stat_statements: Filtering, Regression Testing & moreLukas Fittl
 
Test Case Naming 02
Test Case Naming 02Test Case Naming 02
Test Case Naming 02SriluBalla
 

Was ist angesagt? (20)

Árboles Multicamino, B y B+
Árboles Multicamino, B y B+Árboles Multicamino, B y B+
Árboles Multicamino, B y B+
 
Changepoint Detection with Bayesian Inference
Changepoint Detection with Bayesian InferenceChangepoint Detection with Bayesian Inference
Changepoint Detection with Bayesian Inference
 
Types of performance testing
Types of performance testingTypes of performance testing
Types of performance testing
 
Pertemuan 1 Konsep Dasar Testing
Pertemuan 1 Konsep Dasar TestingPertemuan 1 Konsep Dasar Testing
Pertemuan 1 Konsep Dasar Testing
 
Listas, pilas y colas
Listas, pilas y colasListas, pilas y colas
Listas, pilas y colas
 
Test Cases Maintaining & Documenting
Test Cases Maintaining & DocumentingTest Cases Maintaining & Documenting
Test Cases Maintaining & Documenting
 
Double Loop: TDD & BDD Done Right
Double Loop: TDD & BDD Done RightDouble Loop: TDD & BDD Done Right
Double Loop: TDD & BDD Done Right
 
Code Smells and Its type (With Example)
Code Smells and Its type (With Example)Code Smells and Its type (With Example)
Code Smells and Its type (With Example)
 
Winning data science competitions, presented by Owen Zhang
Winning data science competitions, presented by Owen ZhangWinning data science competitions, presented by Owen Zhang
Winning data science competitions, presented by Owen Zhang
 
Practical learnings from running thousands of Flink jobs
Practical learnings from running thousands of Flink jobsPractical learnings from running thousands of Flink jobs
Practical learnings from running thousands of Flink jobs
 
IR with lucene
IR with luceneIR with lucene
IR with lucene
 
Static Testing
Static Testing Static Testing
Static Testing
 
Algoritmo Heap Sort
Algoritmo Heap SortAlgoritmo Heap Sort
Algoritmo Heap Sort
 
CNIT 127: Ch 18: Source Code Auditing
CNIT 127: Ch 18: Source Code AuditingCNIT 127: Ch 18: Source Code Auditing
CNIT 127: Ch 18: Source Code Auditing
 
Toi uu hoa he thong 30 trieu nguoi dung
Toi uu hoa he thong 30 trieu nguoi dungToi uu hoa he thong 30 trieu nguoi dung
Toi uu hoa he thong 30 trieu nguoi dung
 
Software Testing Basics
Software Testing BasicsSoftware Testing Basics
Software Testing Basics
 
Resilient service to-service calls in a post-Hystrix world
Resilient service to-service calls in a post-Hystrix worldResilient service to-service calls in a post-Hystrix world
Resilient service to-service calls in a post-Hystrix world
 
Equivalence partitions analysis
Equivalence partitions analysisEquivalence partitions analysis
Equivalence partitions analysis
 
Advanced pg_stat_statements: Filtering, Regression Testing & more
Advanced pg_stat_statements: Filtering, Regression Testing & moreAdvanced pg_stat_statements: Filtering, Regression Testing & more
Advanced pg_stat_statements: Filtering, Regression Testing & more
 
Test Case Naming 02
Test Case Naming 02Test Case Naming 02
Test Case Naming 02
 

Ähnlich wie Pruebas unitarias con django

Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и DjangoMoscowDjango
 
Optimization in django orm
Optimization in django ormOptimization in django orm
Optimization in django ormDenys Levchenko
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My PatienceAdam Lowry
 
Designing REST API automation tests in Kotlin
Designing REST API automation tests in KotlinDesigning REST API automation tests in Kotlin
Designing REST API automation tests in KotlinDmitriy Sobko
 
Educate 2017: Customizing Assessments: Why extending the APIs is easier than ...
Educate 2017: Customizing Assessments: Why extending the APIs is easier than ...Educate 2017: Customizing Assessments: Why extending the APIs is easier than ...
Educate 2017: Customizing Assessments: Why extending the APIs is easier than ...Learnosity
 
用Tornado开发RESTful API运用
用Tornado开发RESTful API运用用Tornado开发RESTful API运用
用Tornado开发RESTful API运用Felinx Lee
 
Lo nuevo de Django 1.7 y 1.8
Lo nuevo de Django 1.7 y 1.8Lo nuevo de Django 1.7 y 1.8
Lo nuevo de Django 1.7 y 1.8pedroburonv
 
Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Leonardo Soto
 
Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Leonardo Soto
 
Using Task Queues and D3.js to build an analytics product on App Engine
Using Task Queues and D3.js to build an analytics product on App EngineUsing Task Queues and D3.js to build an analytics product on App Engine
Using Task Queues and D3.js to build an analytics product on App EngineRiver of Talent
 
Py.test
Py.testPy.test
Py.testsoasme
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecturepostrational
 
Django Admin: Widgetry & Witchery
Django Admin: Widgetry & WitcheryDjango Admin: Widgetry & Witchery
Django Admin: Widgetry & WitcheryPamela Fox
 
Selenium my sql and junit user guide
Selenium my sql and junit user guideSelenium my sql and junit user guide
Selenium my sql and junit user guideFahad Shiekh
 
MT_01_unittest_python.pdf
MT_01_unittest_python.pdfMT_01_unittest_python.pdf
MT_01_unittest_python.pdfHans Jones
 
Practical Google App Engine Applications In Py
Practical Google App Engine Applications In PyPractical Google App Engine Applications In Py
Practical Google App Engine Applications In PyEric ShangKuan
 

Ähnlich wie Pruebas unitarias con django (20)

Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
Optimization in django orm
Optimization in django ormOptimization in django orm
Optimization in django orm
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My Patience
 
Designing REST API automation tests in Kotlin
Designing REST API automation tests in KotlinDesigning REST API automation tests in Kotlin
Designing REST API automation tests in Kotlin
 
Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
 
Django (Web Konferencia 2009)
Django (Web Konferencia 2009)Django (Web Konferencia 2009)
Django (Web Konferencia 2009)
 
Educate 2017: Customizing Assessments: Why extending the APIs is easier than ...
Educate 2017: Customizing Assessments: Why extending the APIs is easier than ...Educate 2017: Customizing Assessments: Why extending the APIs is easier than ...
Educate 2017: Customizing Assessments: Why extending the APIs is easier than ...
 
用Tornado开发RESTful API运用
用Tornado开发RESTful API运用用Tornado开发RESTful API运用
用Tornado开发RESTful API运用
 
Lo nuevo de Django 1.7 y 1.8
Lo nuevo de Django 1.7 y 1.8Lo nuevo de Django 1.7 y 1.8
Lo nuevo de Django 1.7 y 1.8
 
Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)
 
Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)
 
Using Task Queues and D3.js to build an analytics product on App Engine
Using Task Queues and D3.js to build an analytics product on App EngineUsing Task Queues and D3.js to build an analytics product on App Engine
Using Task Queues and D3.js to build an analytics product on App Engine
 
Py.test
Py.testPy.test
Py.test
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
 
Django Admin: Widgetry & Witchery
Django Admin: Widgetry & WitcheryDjango Admin: Widgetry & Witchery
Django Admin: Widgetry & Witchery
 
Selenium my sql and junit user guide
Selenium my sql and junit user guideSelenium my sql and junit user guide
Selenium my sql and junit user guide
 
Django tricks (2)
Django tricks (2)Django tricks (2)
Django tricks (2)
 
MT_01_unittest_python.pdf
MT_01_unittest_python.pdfMT_01_unittest_python.pdf
MT_01_unittest_python.pdf
 
Practical Google App Engine Applications In Py
Practical Google App Engine Applications In PyPractical Google App Engine Applications In Py
Practical Google App Engine Applications In Py
 
Django
Django Django
Django
 

Kürzlich hochgeladen

08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 

Kürzlich hochgeladen (20)

08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 

Pruebas unitarias con django

  • 1. Pruebas Unitarias con Django Tomás Henríquez tchenriquez@gmail.com 2-11-2012
  • 2. Historia de las pruebas en el software http://clearspecs.com/joomla15/downloads/ClearSpecs16V01_GrowthOfSoftwareTest.pdf
  • 3. Historia de las pruebas Período orientado al Debugging (antes - 1956)
  • 4. Historia de las pruebas Período orientado a la demostación (1957 - 1978)
  • 5. Historia de las pruebas
  • 6. Historia de las pruebas Período orientado a la destrucción (1979 - 1982)
  • 7. Historia de las pruebas Período orientado a la evaluación (1983 - 1987)
  • 8. Historia de las pruebas “Ninguna técnica puede garantizar software sin errores, sin embargo, un conjunto de técnicas cuidadosamente elegidas para un proyecto en específico puede ayudar a asegurar el desarrollo y mantenimiento de software de calidad para un proyecto”
  • 9. Historia de las pruebas Período orientado a la prevención (1988 - Hoy)
  • 11. Pruebas ¿Cómo uno usualmente prueba su código?
  • 15. Pruebas ¡NO ES FÁCIL! ● Carga de datos para la prueba ● No debe afectar la base de datos ● Super rápidas
  • 17. Carga de datos FIXTURES
  • 18. Carga de datos class Profession(models.Model): name = models.CharField(max_length=30, unique=True) specialist = models.CharField(max_length=30, blank=True)
  • 19. Carga de datos [ { "pk": 1, "model": "my_app.profession", "fields": { "name": "panadero", "specialist": "pizza", } }, { "pk": 2, "model": "my_app.profession", "fields": { "name": "forever_alone", ... ]
  • 20. Carga de datos class Profession(models.Model): name = models.CharField(max_length=30, unique=True) specialist = models.CharField(max_length=30, blank=True) full_time = models.BooleanField(default=False) <----
  • 21. Carga de datos [ { "pk": 1, "model": "my_app.profession", "fields": { "name": "panadero", "specialist": "pizza", "full_time": false, <--- Ay no..... } }, { "pk": 2, "model": "my_app.profession", "fields": { "name": "forever_alone", ... ]
  • 22. Carga de datos [ { "pk": 1, "model": "my_app.profession", "fields": { "name": "panadero", "specialist": "pizza", "full_time": false, <--- Ay no..... } }, { "pk": 2, "model": "my_app.profession", "fields": { "name": "forever_alone", ... ]
  • 23. Carga de datos FIXTURES ¿Para qué son buenos?
  • 24. Carga de datos Estructura del App my_app/ __init__.py models.py fixtures/base.json <------ tests.py
  • 25. Carga de datos class UserTest(TestCase): fixtures = ['base.json'] def setUp(self): pass def tearDown(self): pass def test_coolness(self): # usuario con id == 1 existe gracias al fixture user = User.objects.get(id=1) self.assertTrue(user.is_cool, False) user.become_a_hipster() self.assertTrue(user.is_cool, True)
  • 26. Carga de datos Factories https://github.com/dnerdy/factory_boy
  • 27. Carga de datos Factories ● Organizado <------
  • 28. Carga de datos from django.db import models class Receipt(models.Model): user_id = fields.IntegerField() merchant = fields.CharField(max_length=30) class ReceiptItem(models.Model): name = models.CharField(max_length=30) quantity = models.IntegerField(default=1) alert_sent = models.BooleanField(default=False) receipt = models.ForeignKey(Receipt) class Attach(models.Model): name = models.CharField(max_length=30) item = models.ForeignKey(ReceiptItem)
  • 29. Carga de datos class ReceiptTest(TestCase): fixtures = ['base.json'] def setUp(self): rep = Receipt(user_id=1, merchant='mami') rep.save() ri = ReceiptItem(name='medias', quantity=2, receipt=rep) ri.save() att = Attach(name='foto_de_juanita.jpg', item=ri) att.save() ...
  • 30. Carga de datos class ReceiptTest(TestCase): fixtures = ['base.json'] def setUp(self): rep = Receipt(user_id=1, merchant='mami') rep.save() ri = ReceiptItem(name='medias', quantity=2) ri.save() att = Attach(name='foto_de_juanita.jpg', item=ri) att.save() ...
  • 31. Carga de datos Estructura del App my_app/ __init__.py models.py fixtures/base.json factories.py <------- tests.py
  • 32. Carga de datos class ReceiptFactory(factory.Factory): FACTORY_FOR = Receipt user_id = 1 merchant = "mami" class ReceiptItemFactory(factory.Factory): FACTORY_FOR = ReceiptItem name = factory.Sequence(lambda n: 'item-%s' % n) quantity = 1 receipt = ReceiptFactory() class AttachmentFactory(factory.Factory): FACTORY_FOR = Attachment name = factory.Sequence(lambda n: 'attachment-%s' % n) item = ReceiptItemFactory()
  • 33. Carga de datos class ReceiptTest(TestCase): fixtures = ['base.json'] def setUp(self): ReceiptFactory() ...
  • 37. Carga de datos Factories ● Organizado ● Flexible <-------
  • 38. Carga de datos class ReceiptTest(TestCase): fixtures = ['base.json'] def setUp(self): # No se crea en base de datos ReceiptFactory.build() ...
  • 39. Carga de datos class ReceiptTest(TestCase): fixtures = ['base.json'] def setUp(self): # Crear muchos objects ReceiptFactory.create_batch(5) ...
  • 40. Carga de datos Factories ● Organizado ● Flexible ● Facil de migrar <-------
  • 41. Carga de datos from mongoengine.document import Document, EmbeddedDocument class Attach(EmbeddedDocument): name = fields.StringField(required=True) class ReceiptItem(EmbeddedDocument): name = fields.StringField(required=True) quantity = fields.DecimalField(default=Decimal(1)) alert_sent = fields.BooleanField(default=False) attachments = fields.ListField(fields.EmbeddedDocumentField(Attach)) class Receipt(Document): user_id = fields.IntField(required=True) merchant = fields.StringField(required=True) items = fields.ListField(fields.EmbeddedDocumentField(ReceiptItem))
  • 42. Carga de datos class AttachmentFactory(factory.Factory): FACTORY_FOR = Attachment name = factory.Sequence(lambda n: 'attachment-%s' % n) class ReceiptItemFactory(factory.Factory): FACTORY_FOR = ReceiptItem name = factory.Sequence(lambda n: 'item-%s' % n) quantity = 1 Attachments = [AttachmentFactory.build()] class ReceiptFactory(factory.Factory): FACTORY_FOR = Receipt user_id = 2 merchant = "Amazon" items = [ReceiptItemFactory.build()]
  • 43. Carga de datos class ReceiptTest(TestCase): fixtures = ['base.json'] def setUp(self): ReceiptFactory() ...
  • 44. MOCKERS http://labix.org/mocker http://www.voidspace.org.uk/python/mock/
  • 46. Mockers def tweet(tokens, body): consumer = oauth.Consumer(TWITTER_KEY, settings.TWITTER_SECRET) token = oauth.Token(tokens.oauth, tokens.oauth_secret) client = oauth.Client(consumer, token) header, body = client.request("http://api.twitter.com/1/statuses/" "update.json", "POST", body="status=%s" % body) if header['status'] == '401': return False, ('Twitter account not authorized.' ' Please connect your account again.') body = json.loads(body) if header['status'] != '200': return False, body.get('error', 'Unknown Twitter error') return True, sbody['id_str']
  • 47. Mockers from mocker import Mocker, ARGS, KWARGS class TweetTest(TestCase): fixtures = ['base.json'] def setUp(self): mocker = Mocker() mock_client = mocker.replace('oauth.Client') mock_client.request(ARGS, KWARGS) mocker.response({'code': 200, 'text': 'OK', 'description': 'Success!'}) <---- self.mocker = mocker def test_tweet(self): user = User.objects.get(id=1) self.assertTrue(user.tweets, 0) with self.mocker: res = tweet(user.tokens, 'esto es un Tweet de prueba') self.assertEquals(res, True)
  • 48. Mockers from mocker import Mocker, ARGS, KWARGS class TweetTest(TestCase): fixtures = ['base.json'] def setUp(self): mocker = Mocker() mock_client = mocker.replace('oauth.Client') mock_client.request(ARGS, KWARGS) mocker.throw(ConnectionException) <---- self.mocker = mocker def test_tweet(self): user = User.objects.get(id=1) # Podemos manejar la excepcion? with self.mocker: tweet(user.tokens, 'esto es un Tweet de prueba')
  • 49. Buenas y Malas Practicas
  • 50. Tips ¿Hacer Pruebas antes de lanzar código?
  • 51. Tips MAL def test_gmail(self): expected_msg = { 'subject': 'SeamlessWeb Order', 'plain': '[image: Seamless Web Logo] ...' # MAL 'html': 'n<table width="640" border=...' # MAL } m = Message.objects.get(pk=1) msg = { 'subject': m.subject, 'html': m.body_mimetype_html, 'plain': m.body_mimetype_plain } msg = strip_forwarding(msg) self.assertEqual(msg['subject'], expected_msg['subject']) self.assertEqual(msg['plain'], expected_msg['plain']) self.assertEqual(msg['html'], expected_msg['html'])
  • 52. Tips BIEN def test_gmail(self): strips = ('---------- Forwarded message ----------', 'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ') checks = {'subject': u'SeamlessWeb Order'} msg = strip_forwarding(msg) # Validar que los valores sean los esperados for key, val in checks.items(): self.assertEqual(val, msg[key]) # Asegurar que estos valores no se encuentren en el email for strip in strips: for m in msg.values(): self.assertNotIn(strip, m)
  • 53. Tips No hacer multiples pruebas en una función
  • 54. Tips MAL def test_emails(self): strips = ('---------- Forwarded message ----------', 'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ') checks = {'subject': u'SeamlessWeb Order'} gmail, aol, hotmail = message.objects.all()[:2] msgs = (strip_forwarding(gmail), strip_forwarding(aol), strip_forwarding(hotmail)) for msg in msgs: for key, val in checks.items(): self.assertEqual(val, msg[key]) for strip in strips: for m in msg.values(): self.assertNotIn(strip, m)
  • 55. Tips BIEN def test_gmail(self): strips = ('---------- Forwarded message ----------', 'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ') checks = {'subject': u'SeamlessWeb Order'} gmail = message.objects.get(id=1) msgs = strip_forwarding(gmail) for key, val in checks.items(): self.assertEqual(val, msg[key]) for strip in strips: for m in msg.values(): self.assertNotIn(strip, m) def test_aol(self): strips = ('---------- Forwarded message ----------',...
  • 56. Tips BIEN def test_gmail(self): strips = ('---------- Forwarded message ----------', 'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ') checks = {'subject': u'SeamlessWeb Order'} gmail = message.objects.get(id=1) msgs = strip_forwarding(gmail) for key, val in checks.items(): self.assertEqual(val, msg[key]) for strip in strips: for m in msg.values(): self.assertNotIn(strip, m) def test_aol(self): strips = ('---------- Forwarded message ----------',...
  • 57. Tips Pruebas por Aserción def test_gmail_checks(self): checks = {'subject': u'SeamlessWeb Order'} gmail = message.objects.get(id=1) msgs = strip_forwarding(gmail) for key, val in checks.items(): self.assertEqual(val, msg[key]) <---- Asercion def test_gmail_strips(self): strips = ('---------- Forwarded message ----------', 'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ') gmail = message.objects.get(id=1) msgs = strip_forwarding(gmail) for strip in strips: for m in msg.values(): self.assertNotIn(strip, m) <---- Asercion
  • 58. Tips Pruebas por Acción def test_gmail(self): strips = ('---------- Forwarded message ----------', 'Fwd: ', 'From: ', 'Date: ', 'Subject: ', 'To: ') checks = {'subject': u'SeamlessWeb Order'} gmail = message.objects.get(id=1) msgs = strip_forwarding(gmail) <---- ACCION for key, val in checks.items(): self.assertEqual(val, msg[key]) for strip in strips: for m in msg.values(): self.assertNotIn(strip, m)
  • 59. Tips Probar todas las ramas def handle_coolness(self, user): if user.is_cool: do_cool_stuff(user) else: raise NotCoolDudeException
  • 61. Pruebas de Integración django client library def test_view(self): user = User.objects.get(id=1) url = '/login/' response = self.client.post(url, { 'username': user.username, 'password': 'fakybaby', 'timezone': 'America/Caracas' } self.assertEquals(response.status_code, 200) self.assertEquals(response.cookies_set['logged_name'], User.username)
  • 62. Pruebas de Integración django client library def test_view(self): user = User.objects.get(id=1) url = '/login/' response = self.client.post(url, { 'username': user.username, 'password': 'fakybaby', 'timezone': 'America/Caracas' } self.assertEquals(response.status_code, 200) self.assertEquals(response.cookies_set['logged_name'], User.username)
  • 63. Pruebas de Integración WebTest! def test_view(self): user = User.objects.get(id=1) url = '/login/' form = self.app.get(url).forms['login-form'] form['username'] = user.username form['password'] = 'fakybaby' response = form.submit().follow() self.assertEquals(response.status_code, 200) self.assertEquals(response.cookies_set['logged_name'], user.username)
  • 64. Continuous deployment http://jenkins-ci.org/
  • 65. Continuous Deployment Integrado por django_jenkins Correr Pruebas unitarias Verificacion de codigo (Pep8, jslint, etc) Reportes Emails
  • 66. Continuous Deployment if len(sys.argv) > 1 and sys.argv[1] in ['test', 'jenkins']: # test mongo db MONGO_DBNAME = 'db_test' db = mongoengine.connect(MONGO_DBNAME, username=MONGO_USERNAME, password=MONGO_PASSWORD, host=MONGO_HOST, port=MONGO_PORT, safe=True) db.drop_database(MONGO_DBNAME) # drop entire database

Hinweis der Redaktion

  1. Make sure it runs Make sure it solves the problem
  2. Una ves las aprendes a hacer, siempre es mas rapido hace Pruebas que persistan
  3. Buscar foto que me ayude con el texto Crear info inicial Que no afecte tu base de datos Super Fast!
  4. Buscar foto que me ayude con el texto Crear info inicial Que no afecte tu base de datos Super Fast!
  5. Colorizar este codigo
  6. Colorizar este codigo
  7. Colorizar este codigo
  8. Colorizar este codigo
  9. Colorizar este codigo