Integration Test and Functional Test in plone testing explained

Preface

As a plone developer, I have to do writing lots of unittests for our projects, so I had concerned on plone testing documentation from plone’s official site. Usually I learnt from there about two types of testing, `Integration Testing` and `Functional Testing`. Also knew about Testing Layer and how layer fixture is used while making above kind of tests, in other words which layer fixture is appropriate for which testing, i.e for Functional Testing should be used Functional Testing Layer fixture.

Integration Testing Fixture is generally creating a transaction for each test and just abort the transaction after test being done. Single database(demo storage) is whole test layer lifecycle,  there is not possible to do any persistent activity (transaction commit) in side tests code. Beside Functional Testing Fixture provides database (demo storage) for each test and removed during test teardown (making a stack of database for each test and pop up during tear down process), full transaction lifecycle is happened here, even you could do manually commit and/or use of sub-transaction as well.

By naming (Integration Testing, Functional Testing ) and characteristics  of both, I got confused! my thinking was integration test means collection of components (could be some functions from a module or coming from other modules or api methods from different packages) whether working together perfectly, so here we need persistent features (transaction commit) as we might need to add fixture data and should be available outside of session. For functional test, i thought that this about single component (for example: test single function or method of class), so here we don’t need transaction features, but I was completely wrong (my thought was so stupid)

To get rid out of my confusion, I have planned to dig down into online resources. Very first  I am trying understand that what are meaning of Integration test and Functional test , so ask google and found out from stackoverflow what I was looking for! about Functional testing:

Functional testing is when you test the system against the functional requirements of the product. Product/Project management usually writes these up and QA formalizes the process of what a user should see and experience, and what the end result of those processes should be. Depending on the product this can be automated or not.

Now i have better about those terms and why need persistent feature for Functional Testing

When and where should use each testing type

Integration Testing Fixture

This is relatively faster, you should use it as much as possible, until your test needs (commit) persistent feature. Ideal for testing of methods/functions, where you want to test how those are working together.

Functional Testing Fixture

Primary use case is, when you need to test/monitor after commit reaction of each function/component and make sure data goes to database successfully. If you have SqlAlchemy’s transaction integration, this functional testing fixture is mandatory for you, as some exception/error is thrown by SqlAlchemy during data going to be committed. i.e Integrity violation. Another required case is, when your test will need to use test browser, there you must need completion of transaction lifecycle to avail saved data during assertion. Test browser to be working,  you have to use ZServer Layer Fixture (from plone.app.testing) that is making test server for you.

Naturally Functional testing is slower compared to Integration testing , even it will be getting more slower if you attach ZServer fixture. In my previous experiences, i made functional test fixture with integrating zserver fixture and use this fixture for all of tests (i didn’t care if persistent(transaction commit) is required or not, test browser is needed or not!. ), one of cause, there was my lack of knowledge as result small test took so much time. Now i am learning and have some opinion from me! You should make two functional testing fixture, one without zserver fixture and one with zserver. So if any test needs test browser you will go for with zserver fixture. Bellows are example

from plone.testing import z2
from plone.app.testing import FunctionalTesting
from plone.app.testing import IntegrationTesting

MY_FIXTURE = MyFixtureLayer()
MY_INTEGRATION_TESTING = IntegrationTesting(
 bases=(MY_FIXTURE,),
 name='MyFixtureLayer:IntegrationTesting'
)
MY_FUNCTIONAL_TESTING = FunctionalTesting(
 bases=(MY_FIXTURE, ),
 name='MyFixtureLayer:FunctionalTesting'
)
MY_ZSERVER_FUNCTIONAL_TESTING = FunctionalTesting(
 bases=(
 MY_FIXTURE,
 z2.ZSERVER_FIXTURE),
 name='MyFixtureLayer:ZServerFunctionalTesting'
)

 

Make Sublime Text as the best IDE for full stack python development

Preface

Nothing says from me about Sublime Text 3, I assume you already  know about this nice editor. I can quote from realpython.com blog a very nice article about transforming editor to IDE, published there, I would recommend you look first at there.

Sublime Text 3 (ST3) is lightweight, cross-platform code editor known for its speed, ease of use, and strong community support. It’s an incredible editor right out of the box, but the real power comes from the ability to enhance its functionality using Package Control and creating custom settings.

Unlike above article (from realpython), this article is more specific tutorial like discussion, where you don’t need to more analysis about listed plugins, configurations (of course after starting you will do experiment with all, may find out something I did wrong or need improvement). The main target here, keep ST3 fast as it’s original but with sexy looking and featured with python based development tools and utilities. Bellows demonstration,  I got inspiration from that blog of course and also some of my real life experiences. In this writing, all settings, configurations are based on  Sublime Text 3  build 3126.

Install Sublime Text 3 (ST3)

Actually here nothing much to say about installation of ST3, because they have very good documentation and easy to install binary for all platform. If your OS is not Ubuntu, please ignore following step, because here discussion about install ST3 at Ubuntu in better way.

Good news that we have Ubuntu PPA for ST3, thanks to [@webupd8team] . I would recommend you to install ST3 from ppa, it will gives you lots of flexibility.  Steps are following:

  1. Open your terminal
  2. Add ppa : `~$ sudo add-apt-repository ppa:webupd8team/sublime-text-3`
  3. Install ST3: `~$ sudo apt-get update && sudo apt-get install sublime-text-installer`

Install Required ST3 Packages (Plugins)

First of all you have to install Package Control, please follow corresponding instruction and make sure it is installed. Followings are list of packages (some are required, some are optional and some are recommended)

  1. AdvancedNewFile
  2. AutoPEP8
  3. Git
  4. GitGutter
  5. Gitignore [optional]
  6. Solarized Color Scheme [optional but recommended for good looking]
  7. SideBarEnhancements
  8. SublimeJedi
  9. SublimeLinter
  10. SublimeLinter-annotations
  11. SublimeLinter-csslint
  12. SublimeLinter-flake8 [swipeable with pylint and should one of two]
  13. SublimeLinter-pylint [like no.10 should be choose one of two]
  14. SublimeLinter-html-tidy
  15. SublimeLinter-jshint [nice to have for web application, please follow it’s own documentation before active it]
  16. SublimeLinter-json
  17. SublimeLinter-pyyaml
  18. ProjectManager [optional]
  19. PackageResourceViewer [optional]
  20. Pandoc [optional]
  21. MarkdownEditing [optional]
  22. Markdown Preview [optional]
  23. Restructured​Text Improved [optional]

It is recommended that you install all packages using `Package Control` but you could also install manually, in that case please follow corresponding documentation.

Instruction for installing packages using Package Control

  1. Install Package Control if you haven’t yet.
  2. Use cmd+shift+P then Package Control: Install Package
  3. Search for  certain package, should be appeared in list and install it.
  4. You might need close ST3, to see all changes

Packages selection for `Sublime Text 3` has no restriction, I suggest you explore more packages as much as possible, but always keep in mind that many packages install at a time might enriched your Sublime Text‘s features but in the meantime will keep it busy too! as a result performance decreasing. Plugin/Package you should install and use, only if you know that why need it(package), how it is working, other than any unnecessary package you should avoid and also make sure different packages are not overlapping same feature.  Above listed packages are safe and necessary, but here also depends on development environment, you could add/remove packages from that list.

Note: some of packages need executable path is available at `PATH` variable to work, i.e flake8,  pylint, csslint, etc. Please follow each package documentation. 

Sublime Text 3 Settings

User Setting:

To find user settings, might vary from earlier version to new version. Example from `Sublime Text 3  build 3126` user settings is not directly available in menu, instead you will open default settings (`Preferences > Settings `),  two columns will be opened and one of this is user settings; beside earlier version you will find User Settings directly (`Preferences > Settings User`)

{
    "auto_complete_triggers": [{
        "characters": ".",
        "selector": "source.python"
    }],
    "color_scheme": "Packages/Solarized Color Scheme/Solarized (light).tmTheme",
    "font_size": 12,
    "ignored_packages": [
        "Markdown",
        "RestructuredText",
        "Vintage"
    ],
    "show_line_endings": true,
    "tab_size": 4,
    "translate_tabs_to_spaces": true,
    "trim_automatic_white_space": true,
    "trim_trailing_white_space_on_save": true
}

Above is the basic user settings, you could add more settings, documentation here

Sublime Jedi Settings

  1. Go to Preferences -> Package Settings -> Package Setting -> Jedi -> Settings User 
{
     "auto_complete_function_params": "required",
     "sublime_goto_layout": "single-panel"
}

More settings options could be found here

SublimeLinter Settings

  1. Go to Preferences -> Package Settings -> Package Setting -> SublimeLinter -> Settings User
{
    "user": {
        "debug": false,
        "delay": 0.25,
        "error_color": "D02000",
        "gutter_theme": "Packages/SublimeLinter/gutter-themes/Default/Default.gutter-theme",
        "gutter_theme_excludes": [],
        "lint_mode": "background",
        "linters": {
              "annotations": {
                   "@disable": false,
              },
              "csslint": {
                "@disable": false
              },
              "flake8": {
                   "@disable": false,
                   "max-complexity": 15,
                   "max-line-length": 120
              },
              "htmltidy": {
                "@disable": false
              },
              "jsl": {
                "@disable": false
              },
              "json": {
                  "@disable": false
              },
              "pyyaml": {
                 "@disable": false
              }
         }
    }
}

More about settings, you could find it’s own documentation.

AutoPep8 Settings

  1. Go to Preferences -> Package Settings -> Package Setting -> AutoPep8 -> Settings User 
{
    "max-line-length": 120
}

Known Issues

  1. Sublimelinter-flake8
  2. //platform.twitter.com/widgets.js

Per project settings (sublime-project file)

One of the great feature of Sublime Text is that you could make project specific editor settings (may you already know about it.),  more details here . If you are developing buildout based python project, `plone.recipe.sublimetext` for you!  this is good tool that will manage your project file more effectively.

LRU cache invalidation in python

I am getting sucked during writing one of unit test, because one specific function doesn’t works. After huge time spending, it is revealed that I used lru_cache that’s why it just execute one time (could be by another TestCase).

But in the test environment I need fresh result instead of serving from cache for various reasons.

After googling finally I found out real application of cache invalidation. Bellows are example

from functools import lru_cache
@lru_cache(maxsize=None)
def my_function(arg1, arg2)
   return arg1 + arg2
# Clear Cache before calling
my_function.cache_clear()
my_function(2, 2)

 

Create custom permission in Plone

How To Make Custom Permission [Addons Development]

As a Plone developer we have to deal with several types of permission, for example  `zope2.View`, `cmf.ModifyPortalContent`.  You can also make your own addons specific; you can do it easily from ZMI but I am going show the persistence way  (via zcml)

For example our zcml file name `permissions.zcml`

<configure xmlns="http://namespaces.zope.org/zope">

  <permission id="Your Permission Name as Unique ID"
              title="Your Permission Title ">
    <role name="Role Name"/>
    <role name="Role Name"/>
    ......................
  </permission>
  <permission id="myproduct.addProduct"
              title="My Product Add ">
    <role name="Manager"/>
    <role name="Site Administrator"/>
     ...................... 
   </permission>
</configure>

Activity:

Now add this file in your addon’s configure.zcml

Example:  <include file=”permissions.zcml” />

Plone Tool sets mapping

Plone Built-in Toolsets

Usually I had been using various tools like `portal_catalog`, `portal_setup` provided by CMFPlone. But all time I was curious, where those tools come from, i mean source so that i can inspect their methods, arguments, parameters etc.

  1. “MailHost”: “Products.MailHost.MailHost.MailHost”
  2. “caching_policy_manager”: “Products.CMFCore.CachingPolicyManager.CachingPolicyManager”
  3. “content_type_registry”: “Products.CMFCore.ContentTypeRegistry.ContentTypeRegistry”
  4. “error_log”: “Products.SiteErrorLog.SiteErrorLog.SiteErrorLog”
  5. “plone_utils”: “Products.CMFPlone.PloneTool.PloneTool”
  6. “portal_actions”:  “Products.CMFPlone.ActionsTool.ActionsTool”
  7. “portal_catalog”: “Products.CMFPlone.CatalogTool.CatalogTool”
  8. “portal_controlpanel”: “Products.CMFPlone.PloneControlPanel.PloneControlPanel”
  9. “portal_css”: “Products.ResourceRegistries.tools.CSSRegistry.CSSRegistryTool” [Not used in Plone 5.x any more]
  10. “portal_groupdata”: “Products.PlonePAS.tools.groupdata.GroupDataTool”
  11. “portal_groups”: “Products.PlonePAS.tools.groups.GroupsTool”
  12. “portal_javascripts” : “Products.ResourceRegistries.tools.JSRegistry.JSRegistryTool” [Not used in Plone 5.x any more]
  13. “portal_memberdata”: “Products.PlonePAS.tools.memberdata.MemberDataTool”
  14. “portal_membership”: “Products.PlonePAS.tools.membership.MembershipTool”
  15. “portal_migration”: “Products.CMFPlone.MigrationTool.MigrationTool”
  16. “portal_password_reset”: “Products.PasswordResetTool.PasswordResetTool.PasswordResetTool”
  17. “portal_properties”:  “Products.CMFPlone.PropertiesTool.PropertiesTool”
  18. “portal_quickinstaller”: “Products.CMFPlone.QuickInstallerTool.QuickInstallerTool”
  19. “portal_registration”: “Products.CMFPlone.RegistrationTool.RegistrationTool”
  20. “portal_skins”: “Products.CMFPlone.SkinsTool.SkinsTool”
  21. “portal_types”: “Products.CMFPlone.TypesTool.TypesTool”
  22. “portal_uidannotation”: “Products.CMFUid.UniqueIdAnnotationTool.UniqueIdAnnotationTool”
  23. “portal_uidgenerator”: “Products.CMFUid.UniqueIdGeneratorTool.UniqueIdGeneratorTool”
  24. “portal_uidhandler”: “Products.CMFUid.UniqueIdHandlerTool.UniqueIdHandlerTool”
  25. “portal_diff”: “Products.CMFDiffTool.CMFDiffTool.CMFDiffTool”
  26. “portal_url”: “Products.CMFPlone.URLTool.URLTool”
  27. “portal_view_customizations”: “plone.app.customerize.tool.ViewTemplateContainer”
  28. “portal_workflow”: “Products.CMFPlone.WorkflowTool.WorkflowTool”
  29. “translation_service”: “Products.CMFPlone.TranslationServiceTool.TranslationServiceTool”
  30. “portal_types”: “Products.CMFCore.TypesTool” + “Products.CMFPlone.TypesTool”

How Can I use those Tools
————————-
from Products.CMFCore.utils import getToolByName
from plone.api.portal import get as getPortal
from Acquisition import aq_inner

context = aq_inner(context) or portal or getPortal()
portal_catalog = getToolByName(context, 'portal_catalog')

Toolset Source: {eggs}/Products/CMFPlone/profiles/default/toolset.xml

assign local role in plone through zmi

Assign local role in plone through zmi

While developing application, some times situation may come to need resource specific permission/authorization. For example, you are member of a development team, so you have a office room with 5 desks for you and your colleague, all of you have equal access to enter into the room but in case of your own desk you are the owner! and you have not same permission for other desks to do anything.

For this situation plone provides very easy solution, you can assign local role for each Archetypes content.  So let’s start your application

  1. Go http://{your portal url}/@@usergroup-userprefs and add new user normally. Oh! please remember the usename.
  2. Go http://{your portal url}/{content url}/manage_listLocalRoles . i.e http://localhost:8080/room/mydesk/manage_listLocalRoles
    1. From left `User` type that username and from right `Role` select your desired role. Don’t worry! you can assign any role even owner, manager; it is local role and will only impact on this content.
    2. North Line Hospital
  3. Go http://{your portal url}/portal_workflow/manage_selectWorkflows
    1. Click `update security settings` button bellow.

Now enjoy the benefits!

Date Time format in Python

With my long experiences in programming, we have to do lots of deal with DateTime. Here basically I will demonstrate Python’s `string to datetime` object and `datetime to string format`

from datetime import datetime

# First we will make string date to datetime object
# Example string format is: month/day/year 24hours:minute:seconds
dt = datetime.strptime("09/24/2014 23:09:44", "%m/%d/%Y %H:%M:%S")
print type(dt)
# should be <type ‘datetime.datetime’>

# Now we will produce string representation of python’s datetime object
# Format will be week day name, day, full month name, year 12hour:minute:second AM/PM
print dt.strftime("%A, %d %B, %Y%t%l:%M:%S %p")
# should be Wednesday, 24 September, 2014 11:09:44 PM

List of format directives

  • %a – abbreviated weekday name
  • %A – full weekday name
  • %b – abbreviated month name
  • %B – full month name
  • %c – preferred date and time representation
  • %C – century number (the year divided by 100, range 00 to 99)
  • %d – day of the month (01 to 31)
  • %D – same as %m/%d/%y
  • %e – day of the month (1 to 31)
  • %g – like %G, but without the century
  • %G – 4-digit year corresponding to the ISO week number (see %V).
  • %h – same as %b
  • %H – hour, using a 24-hour clock (00 to 23)
  • %I – hour, using a 12-hour clock (01 to 12)
  • %j – day of the year (001 to 366)
  • %m – month (01 to 12)
  • %M – minute
  • %n – newline character
  • %p – either am or pm according to the given time value
  • %r – time in a.m. and p.m. notation
  • %R – time in 24 hour notation
  • %S – second
  • %t – tab character
  • %T – current time, equal to %H:%M:%S
  • %u – weekday as a number (1 to 7), Monday=1. Warning: In Sun Solaris Sunday=1
  • %U – week number of the current year, starting with the first Sunday as the first day of the first week
  • %V – The ISO 8601 week number of the current year (01 to 53), where week 1 is the first week that has at least 4 days in the current year, and with Monday as the first day of the week
  • %W – week number of the current year, starting with the first Monday as the first day of the first week
  • %w – day of the week as a decimal, Sunday=0
  • %x – preferred date representation without the time
  • %X – preferred time representation without the date
  • %y – year without a century (range 00 to 99)
  • %Y – year including the century
  • %Z or %z – time zone or name or abbreviation
  • %% – a literal % character

Courtesy: Tutorial Point