Install and configure cypress

  1. Add dependency

    1
    npm install -D cypress cypress-image-snapshot
  2. Configure plugin: create a cypress\plugins\index.js file with the following content:

    1
    2
    3
    4
    5
    6
    const { addMatchImageSnapshotPlugin } = 
    require('cypress-image-snapshot\plugin');

    module.exports = (on, config) => {
    addMatchImageSnapshotPlugin(on, config);
    };
  3. Configure support create a cypress\support\index.js file containing:

    1
    2
    3
    import { addMatchImageSnapshotCommand } from 'cypress-image-snapshot\command';

    addMatchImageSnapshotCommand();

Create the screenshot test

“Cypress visits each page of the project and it will take a screenshot of each example in the page”.

  1. Create Cypress configuration (cypress.json)

    1
    2
    3
    4
    {
    "baseUrl": "http:\\localhost:8000\",
    "video": false
    }
  2. Create the test (cypress\integration\screenshot.spec.js)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    const routes = ['badge.html', 'button.html'];

    \\ test based on the routes array
    describe('Component screenshot', () => {
    routes.forEach((route) => {
    const componentName = route.replace('.html', '');
    const testName = `${componentName} should match previous screenshot`;

    it(testName, () => {
    cy.visit(route);

    cy.get('.cypress-wrapper').each((element, index) => {
    const name = `${componentName}-${index}`;

    \\ create one image per .cypress-wrapper element that the page has
    cy.wrap(element).matchImageSnapshot(name);
    });
    });
    });
    });
  3. Create the command to trigger the tests in package.json:

    1
    2
    3
    4
    {
    "test": "cypress",
    "docker-test": "docker run -it -e CYPRESS_updateSnapshots=$CYPRESS_updateSnapshots --ipc=host -v $PWD:\e2e -w \e2e cypress\included:4.11.0"
    }
  4. Run it

    1
    2
    3
    4
    5
    6
    # run headless mode
    npm run cypress run
    # CYPRESS_updateSnapshots=true npm run docker-test

    # use Cypress runner
    npm run cypress open

Brute force (datetime)

1
2
3
4
5
6
import datetime

start_time = datetime.datetime.now()
# insert code snippet here
end_time = datetime.datetime.now()
print(end_time - start_time)

Abstraction (timeit)

Run the snippet a million times and return an average execution time as a result

  • Example snippet

    1
    [(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]
  • Test snippet

    1
    2
    3
    4
    5
    import timeit
    # default: 1 million times
    timeit.timeit("[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]")
    # define the number of times
    timeit.timeit("[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]", number=1000)
  • Further ideas

    • Get a list of execution times
      1
      2
      3
      4
      import timeit
      timeit.repeat("[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]")
      # get the best result
      min(timeit.repeat("[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]"))

Statistics (cProfile)

  • Example snippet

    1
    [(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]
  • Test snippet

    1
    2
    import cProfile
    cProfile.run("[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]")
  • Results data (Row = function that was executed)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    4 function calls in 0.000 seconds 

    Ordered by: standard name

    ncalls tottime percall cumtime percall filename:lineno(function)
    1 0.000 0.000 0.000 0.000 <string>:1(<listcomp>)
    1 0.000 0.000 0.000 0.000 <string>:1(<module>)
    1 0.000 0.000 0.000 0.000 {built-in method builtins.exec}
    1 0.000 0.000 0.000 0.000 {method 'disable' of '\_lsprof.Profiler' objects}
    • ncalls: the number of times that particular function was called
      • This number may actually be written as a fraction (e.g. 3/1) where the first value is the number of total calls and the second value is the number of primitive calls (not recursive).
    • tottime: total amount of time the function spent executing not including calls to subfunctions.
    • percall (first): the ratio of tottime to ncalls (i.e. the average amount of time spent in this function excluding subfunctions).
    • cumtime : the total amount of time the function spent executing including calls to subfunctions.
    • percall (second): the ratio of cumtime to primitive calls (i.e. the average amount of time spent in this function).
    • filename:lineno(function): filename, line number, and function.

External Libraries

Ternary operator

1
2
3
x, y = 10, 20
max = x if x > y else y
print(max)

“all” or “any” conditionals

1
2
3
4
5
6
data = [True, True, False]
if not all(data):
print("Thats right")

if any(data):
print("at least")

Swapping contents of two variables

1
2
3
4
5
6
7
s1 = "Hello"
s2 = "Goodbye"

s2, s1 = s1, s2

print(s2) # Hello
print(s1) # Goodbye

Use f-strings for formatting

1
2
3
4
5
s = "World"
# Classic Python: formatting using format method
print("Hello {0}!".format(s)) # Hello World!
# Python 3.6: format using f-string
print(f"Hello {s}!") # Hello World!

Print a numbered list

1
2
3
4
5
6
7
8
9
10
fruits = ["Apple", "Banana", "Pear", "Orange", "Strawberry"]
for idx, fruit in enumerate(fruits, 1):
print(f"{idx}. {fruit}")

# Output
# 1. Apple
# 2. Banana
# 3. Pear
# 4. Orange
# 5. Strawberry
1
2
3
4
5
6
python = ["Python", "Syntax" , "is", "elegantly"]
python_string = ' '.join(python)
print(python_string)

# Output
# Python Syntax is elegantly

Emojis in Python

1
2
3
4
5
6
import emoji
today = "Weather is :sunny: today! I :heart: it!"
print(emoji.emojize(today, use_aliases=True))

# Output
# Weather is ☀ today! I ❤ it!

Reverse a String

1
2
3
4
5
6
7
8
9
10
11
def is_palindrome(word):
return True if word == word[::-1] else False

s = "Hello"
print(s) # Hello
# Reverse the string
print(s[::-1]) # olleH
print(is_palindrome(s)) # False

w = "racecar"
print(is_palindrome(w)) # True

Remove duplicates from the list

1
2
3
4
5
6
7
8
nums = [1, 5, 22, 30, 15, 12, 33, 15, 22, 1]
# converting list to set removes the duplicate items
unique_nums = list(set(nums))
# Original list
print(nums) # [1, 5, 22, 30, 15, 12, 33, 15, 22, 1]
# unique list
print(unique_nums) # [1, 33, 5, 12, 15, 22, 30]

Iterate over multiple lists at once

1
2
3
4
5
6
7
8
9
10
11
# use zip function
days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday']
temps = [90, 88, 87, 89]
for d, w in zip(days, temps):
print(f"{d}'s temperature is {w}")

# Output
# Sunday's temperature is 90
# Monday's temperature is 88
# Tuesday's temperature is 87
# Wednesday's temperature is 89

Pack / unpack elements

Collected elements into a single tuple using *<param_name> syntax.

Pack

1
2
3
4
5
6
7
def add_nums(*args):
sum = 0
for num in args:
sum += num
return sum

print(f"Sum = {add_nums(3, 5, 7, 9)}") # Sum = 24

Unpack

1
2
3
4
def avg(a, b, c):
return (a + b + c) / 4

print(f"Average = {avg(*[10, 20, 30])}") # Average = 15.0

Merge two dictionaries

1
2
3
4
5
6
d1={'Apple' : 5}
d2={'Orange' : 4, 'Banana' : 3}
# unpack dictionaries via `**``
#merge via `{}``
result = {**d1,**d2}
print(result) # {‘Apple’ : 5, ‘Orange’: 4, ‘Banana’: 3}

Check if all the elements of one list is in another list

1
2
3
4
5
6
list1 = ['Hi' ,  'hello', 'master', 'world', 'list']
list2 = ['world' , 'hello', 'Hi']

result = all(elem in list1 for elem in list2)

print(result) # True

Pypi

  • PyPi (Python Packaging index)
    • Repository called by pip install
    • The python utility twine helps uploading the package

Twine

  • Install
    1
    python -m pip install twine
  • Generate distribution
    1
    2
    3
    # go to the directory of the code you want to upload
    python -m setup.py sdist
    # the distribution has been created under a 'dist folder'
  • Upload
    1
    python -m twine upload dist/Helloworld-1.0.tar.gz

Package content

  • The directory name must be the same name you want to give to the package (consider chacking if the name is available in pypi)

    1. .py python code files
      • remove print instructions
      • you need to have a class, and a method inside the class
    2. setup.py code file
    3. __init__.py code file
    4. setup.cfg file
    5. README.md file
    6. License File
  • Example:

    1
    2
    3
    4
    5
    6
    7
    setup.py
    README.md
    LICENSE.txt (inside the folder)
    Helloworld (Folder)
    ||-- __init__.py (inside the folder)
    ||-- Helloworld.py (inside the folder)
    ||-- setup.cfg (inside the folder)

The setup.py file

  • Example:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    import io
    import os
    import sys
    import setuptools
    from setuptools import find_packages, setup, Command

    with open("README.md", "r") as fh:
    long_description = fh.read()

    setup(
    # directory name
    name = 'Helloworld',
    # same as above
    packages = ['Helloworld'],
    version = '1.0',
    license='GPLv3',
    description = "Python library that says Hello World when called.",
    # pass it to readme
    long_description=long_description,
    long_description_content_type="text/markdown",
    author = 'XXX',
    author_email = 'xxx@email.com',
    url = 'https://gitlab.com/xxx/Helloworld',
    # my package
    py_modules=['mypackage'],
    entry_points={'console_scripts': ['mycli=mymodule:cli'],},
    # tags
    keywords = ['Simple'],
    # scale it as the library grows
    classifiers=[
    'Development Status :: 4 - Beta',
    'Intended Audience :: Developers',
    'Topic :: Software Development :: Build Tools',
    'License :: GNU General Public License (GPL) :: GPLv3',
    'Programming Language :: Python :: 3.4',
    'Programming Language :: Python :: 3.5',
    'Programming Language :: Python :: 3.6'
    ],
    # minimum python version required
    python_requires='>=3.1',
    )

The __init__.py file

  • Either leave it empty, so python autogenerates, or import class name and method
    1
    from Helloworld.Helloworld import Helloworld

The setup.cfg file

  • It helps handling the metadata
    1
    2
    [metadata]
    description-file = README.md

The readme.md file

  • Markdown file presenting your package and giving installation instructions

The license.txt file

Pre-requisites

  • Install AWS CLI.
  • Configure it.
    1
    aws configure
  • Check it worked.
    1
    aws s3 ls

First contact with templates

  • Minimum example correction.
    • Initial script.
      1
      2
      3
      4
      5
      6
      7
      aws cloudformation create-stack \
      --template-body file:\\lamp-as.json \
      --stack-name lamp \
      --parameters \
      ParameterKey=KeyName,ParameterValue=mykey
      # won't work, needs more network elements information
      # such as VPCs, subNets info and DB access
    • Retrieve the lacking information from the CLI.
      1
      2
      aws ec2 describe-vpcs
      aws ec2 describe-subnets
    • Complete template.
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      aws cloudformation create-stack \
      --template-body file:\\lamp-as.json \
      --stack-name lamp-as \
      --parameters \
      ParameterKey=KeyName,
      ParameterValue=mykey \
      ParameterKey=VpcId, \
      ParameterValue=vpc-1ffbc964 \
      ParameterKey=Subnets, \
      ParameterValue=\'subnet-0e170b31,subnet-52d6117c\' \
      ParameterKey=DBUser, \
      ParameterValue=myadmin \
      ParameterKey=DBPassword, \
      ParameterValue=mypass23
    • Once it is launched, verify.
      • Cloudformation is running.
        1
        aws cloudformation describe-stacks
      • EC2 instances are running.
        1
        2
        3
        4
        aws ec2 describe-instances \
        --filters Name=instance-state-name,Values=running \
        --query 'Reservations[*].Instances[*]\
        .{Instance:InstanceId,PublicIPAddress:PublicIpAddress}'

Get help for filling up more AWS fields

  • Retrieve information about stacks.
    1
    aws cloudformation describe-stacks
  • Define the EC2 instance type on template.
    • You may swap that default value for any of the other AllowedValues, or override it from the CLI.
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      "Parameters" : {
      "KeyName": {
      "Description" : "Name of an existing EC2 KeyPair to enable SSH access to the instance",
      "Type": "AWS::EC2::KeyPair::KeyName",
      "ConstraintDescription" : "must be the name of an existing EC2 KeyPair."
      },

      "InstanceType" : {
      "Description" : "WebServer EC2 instance type",
      "Type" : "String",
      "Default" : "t2.small",
    • Check Mappings section,to review available hardware architectures and AMI identifiers for each region.
      • Optional section, you can insert your own non-standard values organized into key\value pairs.
        1
        2
        3
        4
        5
        "Mappings" : {
        "AWSInstanceType2Arch" : {
        "t1.micro" : { "Arch" : "HVM64" },
        "t2.nano" : { "Arch" : "HVM64" },
        "t2.micro" : { "Arch" : "HVM64" },
      • The Resources section in this case defines your instance environment (public IP address is associated with the new Elastic IP address that will be allocated).
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        "Resources" : {
        # ...
        "InstanceSecurityGroup" : {
        "Type" : "AWS::EC2::SecurityGroup",
        "Properties" : {
        "GroupDescription" : "Enable SSH access via port 22",
        "SecurityGroupIngress" : [ {
        "IpProtocol" : "tcp",
        "FromPort" : "22",
        "ToPort" : "22",
        "CidrIp" : { "Ref" : "SSHLocation"}
        } ]
        }
        }
        },

Get help with external stacks

  • Quick Starts - pre-built infrastructure stacks that are provided here to help you create more complex cloud deployments by third-party companies to simplify the process of building their infrastructure in within the AWS platform.
0%