Monday, December 31, 2018

Flask Assignment and Solution for Health On Demand.

Interview At Health On Demand :

After Puzzle and Face to Face round I got an assignment to build in Python-Flask in a week. I Haven't touched flask in 4 yrs and that is why it was quite challenging but I did it.

Flask usually doesn't have any project structure like Django or Pyramid.
I got selected and this task helped me a lot to convert HODs Monolith code base into micro-services.

Problem Statement : 

A fictitious health-care startup that does health checks for multiple connected instruments. The instruments currently save results via mobile client when all check-ups are done, it does the bulk upload reports.

The organization is having trouble with querying it's a single source of truth database ( PostgreSQL) and need to transforming and migrating user reports data to separate database ( NoSQL ) on a periodic basis to store and serve user report data via the mobile client.

The project contains two services along with documentation,

MyHealthApp: to collect reports from doctors and machine
ReportsApp: for clients to browse the reports.

Additional Task
- Write Test Case
- REST-API testing with Postman
- API Documentation

Details and Code can be found at Github  https://github.com/codetarsier/MyHealthApp/ 

Solution Goes Here
Reading Material
ClassBasedViews:  http://flask.pocoo.org/docs/0.12/views/#method-views-for-apis
Flask Blueprint:  https://exploreflask.com/en/latest/blueprints.html























System Workflow
  1. User comes for a health checkup
  2. With HealthCheckup Machine doctor does the health checkup and machine stores all these reports in its local memory.
  3. MyHealthCheckupApp mobile/tab application pulls those reports from HC-Machine.
  4. MyHealthCheckupApp sends all the reports to MyHealthApp-API backend server.
  5. TaskRunner runs a background task and keeps checking for the new record on some interval ( Interval Time can be set in the settings file ). TaskRunner fetches the record and stores last checkup-reportID and when next time it runs, it fetches the incremental reports from previously-stored checkup-reportID.
  6. TaskRunner converts these reports into JSON then it sends them to ReportsApp-Server using ReportsAPI.
  7. Client/Customer login into ReportsApp mobile application and browse those reports from ReportsApp-API backend server.
  8. When the client provides username/password it gets authenticated from MyHealthApp-API.
  9. After authentication users can browse Reports.

Project Structure of 1. My Health App


├── LICENSE
├── README.md
├── docs
│   ├── postman-api-collections
│   └── postman-api-docs
├── myhealthapp
│   ├── applications
│   │   ├── __init__.py
│   │   ├── checkups
│   │   │   ├── __init__.py
│   │   │   ├── models.py
│   │   │   └── views.py
│   │   ├── common
│   │   │   ├── __init__.py
│   │   │   └── models.py
│   │   ├── machines
│   │   │   ├── __init__.py
│   │   │   ├── models.py
│   │   │   └── views.py
│   │   └── profiles
│   │       ├── __init__.py
│   │       ├── models.py
│   │       └── views.py
│   ├── config
│   │   ├── __init__.py
│   │   ├── development_sqlite.db
│   │   ├── secrets.json
│   │   └── settings.py
│   ├── manage.py
│   ├── migrations
│   │   ├── README
│   │   ├── alembic.ini
│   │   ├── env.py
│   │   ├── script.py.mako
│   │   └── versions
│   │       ├── 4cecc0d2ed8a_.py
│   │       └── cc805ab1bc28_.py
│   └── tests
│       ├── __init__.py
│       └── test_flaskr.py
└── requirements.txt

Project Structure of 2. Reports App
├── README.md
├── config
│   ├── __init__.py
│   ├── __pycache__
│   ├── secrets.json
│   └── settings.py
├── docs
│   └── ReportsAPIs.postman_collection.json
├── manage.py
├── reports
│   ├── __pycache__
│   ├── managers.py
│   ├── models.py
│   └── views.py
├── requirements.txt
├── tests
│   ├── __init__.py
│   ├── __pycache__
│   ├── conftest.py
│   ├── flask_test.cfg
│   └── test_user_reports.py
└── utils
    ├── __pycache__
    ├── random_hex.py
    ├── response_handler.py
    └── rest_auth.py

Thanks.

Share:

Wednesday, December 5, 2018

Tuesday, December 4, 2018

Monday, November 19, 2018

Working with Multiple Databases in Django.

Working with Multiple Databases in Django.

As usual django-doc is great to start with any topics. I was just giving a try to use multiple database in single application.

1. Database Settings

First step is to tell your django application that you want to use more than one database. So look for the DATABASES in your project's settings.py file.
project/settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'blogs': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'blogs_db.sqlite3')
    }
}
Here I'm going to store all the blog entries into "blogs" ( blogs_db.sqlite3 ) and rest data will be stored in into "default" database ( db.sqlite3 ).

2. Define Model

blogs/models.py

from django.db import models

class Blog(models.Model):
    title = models.CharField(max_length=200)

3. Setup Database Router

You can define a database router that implements a policy constraining the availability of particular models.
project/settings.py
DATABASE_ROUTERS = ['blogs.router.BlogRouter']
blogs/router.py

class BlogRouter:
    """
    A router to control all database operations on models in the
    auth application.
    """
    def db_for_read(self, model, **hints):
        """
        Attempts to read auth models go to auth_db.
        """
        if model._meta.app_label == 'blogs':
            return 'blogs'
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth models go to auth_db.
        """
        if model._meta.app_label == 'blogs':
            return 'blogs'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth app is involved.
        """
        if obj1._meta.app_label == 'blogs' or \
           obj2._meta.app_label == 'blogs':
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth app only appears in the 'auth_db'
        database.
        """
        if app_label == 'blogs':
            return db == 'blogs'
        return None
That's it. Now test whether the settings are working fine or not?
./manage.py makemigrations --database=default
./manage.py makemigrations --database=blogs

4. Create Blog

There are multiple ways to create blog entry in blogs_db,

4.1. By using "using()" to create entry in perticular db.
example,
from blogs.models import Blog
Blog.objects.using('blogs').create(title='python goes here')

4.2. Create a blog through admin interface.

blogs/admin.py

from django.contrib import admin
from .models import Blog

admin.site.register(Blog)

5. Test Your Config Using Shell

Create a blog entry using the admin site and will check which database has stored the blog info.
./manage.py shell

from blogs.models import Blog

 # This will run on the DEFAULT-DATABASE/BLOG-DATABASE
Blog.objects.all() 
QuerySet [Blog: Blog object (1)]

 # This will run on the BLOGS-DATABASE
Blog.objects.using('blogs').all()
QuerySet [Blog: Blog object (1)]
# returns blogs

 #This will run on the DEFAULT-DATABASE
Blog.objects.using('default').all()

    301             return Database.Cursor.execute(self, query)
    302         query = self.convert_query(query)
--> 303         return Database.Cursor.execute(self, query, params)
    304
    305     def executemany(self, query, param_list):
OperationalError: no such table: blogs_blog
returns error.
For more detail please visit, https://docs.djangoproject.com/en/2.1/topics/db/multi-db/
Share:

Sunday, August 12, 2018

Beauty of Gateway Of India and Tajmahal Palace Hotel


The Taj Mahal Palace Hotel

The Taj Mahal Palace Hotel is a heritage, five-star luxury hotel in the Colaba region of Mumbai, Maharashtra, India, situated next to the Gateway of India. Historically it was known as the "Taj Mahal Hotel" or the "Taj Palace Hotel" or simply "the Taj".

The Gateway of India

The Gateway of India is an arch monument built during the 20th century in BombayIndia. The monument was erected to commemorate the landing of King George V and Queen Mary at Apollo Bunder on their visit to India in 1911.


Share:

Thursday, August 2, 2018

Python Selenium : Generating the HTML Test Report and Screenshot feature.

Python Selenium : HtmlTestRunner and Screenshot feature.

Introduction

HtmlTest runner
HtmlTest runner is a unittest test runner that save test results in Html files, for human readable presentation of results.

Screenshots
In automation, it is mandatory to take the screenshot for verification so that can prove also that your test case has covered certain functionality or not. Screenshots help you a lot when your test case will fail so that you can identify what went wrong in your script or in your application.

1. HtmlTestRunner Installation

You can install and read more about HtmlTestRunner from the Github..
HtmlTestRunner Github Page
Using pip, you can install selenium like this:
pip install html-testRunner

2. Sample Selenium Test

create pythonorg-sample.py

import unittest
import HtmlTestRunner
from selenium import webdriver
from selenium.webdriver.common.keys import Keys


class PythonOrgSearch(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Chrome()

    def test_search_in_python_org(self):
        driver = self.driver
        driver.get("http://www.python.org")

        # take screen shot
        self.driver.save_screenshot("python-org.png")

        elem = driver.find_element_by_name("q")
        elem.send_keys("pycon")
        elem.send_keys(Keys.RETURN)

        # take screen shot after search
        self.driver.save_screenshot("python-org-after-search.png")

        assert "No results found." not in driver.page_source

    def test_error(self):
        """ This test should be marked as error one. """
        raise ValueError

    def test_fail(self):
        """ This test should fail. """
        self.assertEqual(1, 2)

    def tearDown(self):
        self.driver.close()


if __name__ == "__main__":
    unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='report'))

3. Run Selenium Test

python pythonorg-sample.py

4. Screenshots

HtmlTestRunner
Console Log

Running tests...
----------------------------------------------------------------------
 This test should be marked as error one. ... ERROR (1.961452)s
 This test should fail. ... FAIL (1.838222)s
 test_search_in_python_org (__main__.PythonOrgSearch) ... OK (12.246906)s

======================================================================
ERROR [1.961452s]: This test should be marked as error one.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "pythonorg-sample.py", line 31, in test_error
    raise ValueError
ValueError

======================================================================
FAIL [1.838222s]: This test should fail.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "pythonorg-sample.py", line 35, in test_fail
    self.assertEqual(1, 2)
AssertionError: 1 != 2

----------------------------------------------------------------------
Ran 3 tests in 0:00:16

FAILED
 (Failures=1, Errors=1)

Generating HTML reports...

Share:

Wednesday, August 1, 2018

Getting Started with Python Selenium on Mac OS X

1. Introduction

Selenium Python bindings provides a simple API to write functional/acceptance tests using Selenium WebDriver. Through Selenium Python API you can access all functionalities of Selenium WebDriver in an intuitive way. Selenium Python bindings provide a convenient API to access Selenium WebDrivers like Firefox, Ie, Chrome, Remote etc. The current supported Python versions are 2.7, 3.5 and above.

2. Downloading Python bindings for Selenium and Installation

You can download Python bindings for Selenium from the PyPI page for selenium package. However, a better approach would be to use pip to install the selenium package. Python 3.6 has pip available in the standard library. Using pip, you can install selenium like this:
pip install selenium

3. Drivers

download chrome driver

Selenium requires a driver to interface with the chosen browser. Firefox, for example, requires geckodriver, which needs to be installed before the below examples can be run. Make sure it’s in your PATH, e. g., place it in /usr/bin or /usr/local/bin.
cp chromedriver /usr/local/bin/

4. Sample Selenium Test

create main.py file

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome()
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element_by_name("q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()

5. Run Script

python main.py
Share:

Saturday, June 16, 2018

Thursday, April 19, 2018

Friday, February 9, 2018

Music for workspace


Best of Synthwave And Retro Electro Music Mix




One workspace dedicated to music on mac, and another completely for getting things done Or you can attach a dedicated monitor for music.

I came across this amazing playlist collection of electro music which is quite impressive and it won't disturb you while you are working.
Share:

Friday, January 5, 2018