tests: infrastructure to rebuild and export all business templates

This is not really a test, but it reuses runUnitTest/runTestSuite
commands, because they are good tools to quickly create ERP5
environment and installing business templates.

To re-build and re-export all* business templates, use this command:

    ./bin/runTestSuite --test_suite=ReExportERP5BusinessTemplateTestSuite

--node_quantity argument can also be used to process multiple
business templates in parallel.

* note that this does not actually handle all business templates, but
only the ones for which coding style test is enabled, because most
business templates for which it is not enabled can not be installed.

This typically produces large diffs that should apply the same
change to many files and ideally, nothing else. We also developed a
simple tool which summarize the diff by detecting the same chunk
present in multiple files, it can be found at
https://lab.nexedi.com/nexedi/erp5/snippets/1171 and also below.

---

from __future__ import print_function
"""report similar hunks in a patch.
"""
__version__ = '0.1'

import argparse
import collections
import codecs
import unidiff # unidiff==0.7.3
import hashlib

parser = argparse.ArgumentParser()
parser.add_argument('patch_file', type=argparse.FileType('r'), default='-', nargs='?')
parser.add_argument('-v', '--verbose', action='count', default=0)
args = parser.parse_args()

patchset = unidiff.PatchSet(codecs.getreader('utf-8')(args.patch_file))

chunks_by_filenames = collections.defaultdict(set)

for patch in patchset:
  for chunk in patch:
    chunk_text = u''.join([unicode(l) for l in chunk])
    chunks_by_filenames[chunk_text].add(patch.path)

for chunk_text, filenames in chunks_by_filenames.items():
  chunk_hash = hashlib.md5(chunk_text.encode('utf-8')).hexdigest()
  print("Chunk %s is present in %s files" % (chunk_hash, len(filenames)))
  if args.verbose:
    print()
    print("\n".join("  " + f for f in sorted(filenames)))
    print()
  if args.verbose > 1:
    print()
    print(chunk_text)
    print()
6 jobs for master in 0 seconds
Status Job ID Name Coverage
  External
passed ERP5.CodingStyleTest-Master

00:41:03

passed ERP5.PerformanceTest-Master

00:26:58

failed ERP5.UnitTest-Master

04:21:14

failed ERP5.UnitTest-Master.Medusa

04:19:18

passed SlapOS.Eggs.UnitTest-Master.Python2

00:11:33

passed SlapOS.Eggs.UnitTest-Master.Python3

00:14:05