Commit dd00c75c authored by Jérome Perrin's avatar Jérome Perrin

accounting_l10n_fr: more fixes for FEC

See merge request nexedi/erp5!1767
parents 5162d9e3 968c3f7b
# coding: utf-8 # coding: utf-8
import unicodedata
from cStringIO import StringIO from cStringIO import StringIO
import zipfile import zipfile
from Products.ERP5Type.Message import translateString from Products.ERP5Type.Message import translateString
...@@ -13,15 +14,13 @@ fec_file = context.AccountingTransactionModule_viewComptabiliteAsFECXML( ...@@ -13,15 +14,13 @@ fec_file = context.AccountingTransactionModule_viewComptabiliteAsFECXML(
at_date=at_date, at_date=at_date,
result_list=result_list) result_list=result_list)
if test_compta_demat_compatibility: if test_compta_demat_compatibility:
fec_file = (fec_file # normalize all non ascii characters (é => e), while still keeping
# some "important" characters such as €
# https://github.com/DGFiP/Test-Compta-Demat/issues/37 # https://github.com/DGFiP/Test-Compta-Demat/issues/37
.replace(u"’", u"'")
.replace(u"Œ", u"OE")
.replace(u"œ", u"oe")
.replace(u"Ÿ", u"Y")
# https://github.com/DGFiP/Test-Compta-Demat/issues/39 # https://github.com/DGFiP/Test-Compta-Demat/issues/39
.replace(u"€", u"EUR") fec_file = unicodedata.normalize(
) 'NFKD', fec_file.replace(u"€", "EUR")
).encode('ascii', 'ignore')
zipbuffer = StringIO() zipbuffer = StringIO()
zipfilename = at_date.strftime('FEC-%Y%m%d.zip') zipfilename = at_date.strftime('FEC-%Y%m%d.zip')
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<ValidDate tal:content="python: context.AccountingTransaction_getDeliverDate().strftime('%Y-%m-%d')">Modification Date</ValidDate> <ValidDate tal:content="python: context.AccountingTransaction_getDeliverDate().strftime('%Y-%m-%d')">Modification Date</ValidDate>
<tal:block tal:repeat="line python:context.contentValues(portal_type=context.getPortalAccountingMovementTypeList())"><ligne <tal:block tal:repeat="line python:context.contentValues(portal_type=context.getPortalAccountingMovementTypeList())"><ligne
tal:define="account python:line.getDestinationValue(portal_type='Account')" tal:define="account python:line.getDestinationValue(portal_type='Account')"
tal:condition="python: account is not None and (line.getQuantity() or line.getDestinationAssetDebit() or line.getDestinationAssetCredit() or not options['test_compta_demat_compatibility'])"> tal:condition="python: account is not None and ((line.getDestinationTotalAssetPrice() if line.hasDestinationTotalAssetPrice() else line.getQuantity()) or not options['test_compta_demat_compatibility'])">
<CompteNum tal:content="account/Account_getGapId">Reference Compte (Account_getGapId)</CompteNum> <CompteNum tal:content="account/Account_getGapId">Reference Compte (Account_getGapId)</CompteNum>
<CompteLib tal:content="line/Movement_getDestinationCompteLib">Translated Title Compte</CompteLib> <CompteLib tal:content="line/Movement_getDestinationCompteLib">Translated Title Compte</CompteLib>
<tal:block tal:condition="python: account.getAccountType() in ('asset/receivable', 'liability/payable')" <tal:block tal:condition="python: account.getAccountType() in ('asset/receivable', 'liability/payable')"
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<CompteAuxLib tal:content="third_party/getTitle"></CompteAuxLib></tal:block><tal:block> <CompteAuxLib tal:content="third_party/getTitle"></CompteAuxLib></tal:block><tal:block>
<Montantdevise></Montantdevise> <Montantdevise></Montantdevise>
<Idevise></Idevise></tal:block> <Idevise></Idevise></tal:block>
<Debit tal:content="python: '%0.2f' % (line.getDestinationAssetDebit() or line.getDestinationDebit())"></Debit> <Debit tal:content="python: '%0.2f' % (line.getDestinationAssetDebit() if line.hasDestinationTotalAssetPrice() else line.getDestinationDebit())"></Debit>
<Credit tal:content="python: '%0.2f' % (line.getDestinationAssetCredit() or line.getDestinationCredit())"></Credit> <Credit tal:content="python: '%0.2f' % (line.getDestinationAssetCredit() if line.hasDestinationTotalAssetPrice() else line.getDestinationCredit())"></Credit>
</ligne></tal:block> </ligne></tal:block>
</ecriture> </ecriture>
\ No newline at end of file
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<ValidDate tal:content="python: context.AccountingTransaction_getDeliverDate().strftime('%Y-%m-%d')">Modification Date</ValidDate> <ValidDate tal:content="python: context.AccountingTransaction_getDeliverDate().strftime('%Y-%m-%d')">Modification Date</ValidDate>
<tal:block tal:repeat="line python:context.contentValues(portal_type=context.getPortalAccountingMovementTypeList())"><ligne <tal:block tal:repeat="line python:context.contentValues(portal_type=context.getPortalAccountingMovementTypeList())"><ligne
tal:define="account python:line.getSourceValue(portal_type='Account')" tal:define="account python:line.getSourceValue(portal_type='Account')"
tal:condition="python: account is not None and (line.getQuantity() or line.getSourceAssetDebit() or line.getSourceAssetCredit() or not options['test_compta_demat_compatibility'])"> tal:condition="python: account is not None and ((line.getSourceTotalAssetPrice() if line.hasSourceTotalAssetPrice() else line.getQuantity()) or not options['test_compta_demat_compatibility'])">
<CompteNum tal:content="account/Account_getGapId">Reference Compte (Account_getGapId)</CompteNum> <CompteNum tal:content="account/Account_getGapId">Reference Compte (Account_getGapId)</CompteNum>
<CompteLib tal:content="line/Movement_getSourceCompteLib">Translated Title Compte</CompteLib> <CompteLib tal:content="line/Movement_getSourceCompteLib">Translated Title Compte</CompteLib>
<tal:block tal:condition="python: account.getAccountType() in ('asset/receivable', 'liability/payable')" <tal:block tal:condition="python: account.getAccountType() in ('asset/receivable', 'liability/payable')"
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<CompteAuxLib tal:content="third_party/getTitle"></CompteAuxLib></tal:block><tal:block> <CompteAuxLib tal:content="third_party/getTitle"></CompteAuxLib></tal:block><tal:block>
<Montantdevise></Montantdevise> <Montantdevise></Montantdevise>
<Idevise></Idevise></tal:block> <Idevise></Idevise></tal:block>
<Debit tal:content="python: '%0.2f' % (line.getSourceAssetDebit() or line.getSourceDebit())"></Debit> <Debit tal:content="python: '%0.2f' % (line.getSourceAssetDebit() if line.hasSourceTotalAssetPrice() else line.getSourceDebit())"></Debit>
<Credit tal:content="python: '%0.2f' % (line.getSourceAssetCredit() or line.getSourceCredit())"></Credit> <Credit tal:content="python: '%0.2f' % (line.getSourceAssetCredit() if line.hasSourceTotalAssetPrice() else line.getSourceCredit())"></Credit>
</ligne></tal:block> </ligne></tal:block>
</ecriture> </ecriture>
\ No newline at end of file
...@@ -137,7 +137,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -137,7 +137,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
account_module = self.portal.account_module account_module = self.portal.account_module
self._makeOne( self._makeOne(
portal_type='Purchase Invoice Transaction', portal_type='Purchase Invoice Transaction',
title='Première Écriture', title='Premiere Ecriture',
simulation_state='delivered', simulation_state='delivered',
reference='1', reference='1',
source_section_value=self.organisation_module.supplier, source_section_value=self.organisation_module.supplier,
...@@ -151,7 +151,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -151,7 +151,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
self._makeOne( self._makeOne(
portal_type='Sale Invoice Transaction', portal_type='Sale Invoice Transaction',
title='Seconde Écriture', title='Seconde Ecriture',
simulation_state='delivered', simulation_state='delivered',
reference='2', reference='2',
destination_section_value=self.organisation_module.client_2, destination_section_value=self.organisation_module.client_2,
...@@ -188,7 +188,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -188,7 +188,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
account_module = self.portal.account_module account_module = self.portal.account_module
self._makeOne( self._makeOne(
portal_type='Purchase Invoice Transaction', portal_type='Purchase Invoice Transaction',
title='Première Écriture', title='Premiere Ecriture',
simulation_state='delivered', simulation_state='delivered',
ledger='accounting/general', ledger='accounting/general',
reference='1', reference='1',
...@@ -203,7 +203,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -203,7 +203,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
self._makeOne( self._makeOne(
portal_type='Sale Invoice Transaction', portal_type='Sale Invoice Transaction',
title='Seconde Écriture', title='Seconde Ecriture',
simulation_state='delivered', simulation_state='delivered',
ledger='accounting/general', ledger='accounting/general',
reference='2', reference='2',
...@@ -218,7 +218,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -218,7 +218,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
self._makeOne( self._makeOne(
portal_type='Sale Invoice Transaction', portal_type='Sale Invoice Transaction',
title='Troisième Écriture', title='Troisieme Ecriture',
simulation_state='delivered', simulation_state='delivered',
ledger='accounting/detailed', ledger='accounting/detailed',
reference='3', reference='3',
...@@ -254,7 +254,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -254,7 +254,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
journal = journal_list[0] journal = journal_list[0]
ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")]) ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")])
self.assertEqual(['Première Écriture'], ecriture_list) self.assertEqual(['Premiere Ecriture'], ecriture_list)
debit_list = journal.xpath(".//Debit") debit_list = journal.xpath(".//Debit")
self.assertEqual(3, len(debit_list)) self.assertEqual(3, len(debit_list))
...@@ -270,7 +270,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -270,7 +270,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
journal = journal_list[0] journal = journal_list[0]
ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")]) ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")])
self.assertEqual(['Seconde Écriture'], ecriture_list) self.assertEqual(['Seconde Ecriture'], ecriture_list)
debit_list = journal.xpath(".//Debit") debit_list = journal.xpath(".//Debit")
self.assertEqual(3, len(debit_list)) self.assertEqual(3, len(debit_list))
...@@ -290,7 +290,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -290,7 +290,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
journal = journal_list[0] journal = journal_list[0]
ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")]) ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")])
self.assertEqual(['Première Écriture'], ecriture_list) self.assertEqual(['Premiere Ecriture'], ecriture_list)
debit_list = journal.xpath(".//Debit") debit_list = journal.xpath(".//Debit")
self.assertEqual(3, len(debit_list)) self.assertEqual(3, len(debit_list))
...@@ -306,7 +306,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -306,7 +306,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
journal = journal_list[0] journal = journal_list[0]
ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")]) ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")])
self.assertEqual(['Seconde Écriture', 'Troisième Écriture'], ecriture_list) self.assertEqual(['Seconde Ecriture', 'Troisieme Ecriture'], ecriture_list)
debit_list = journal.xpath(".//Debit") debit_list = journal.xpath(".//Debit")
self.assertEqual(6, len(debit_list)) self.assertEqual(6, len(debit_list))
...@@ -325,7 +325,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -325,7 +325,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
journal = journal_list[0] journal = journal_list[0]
ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")]) ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")])
self.assertEqual(['Première Écriture', 'Seconde Écriture'], ecriture_list) self.assertEqual(['Premiere Ecriture', 'Seconde Ecriture'], ecriture_list)
debit_list = journal.xpath(".//Debit") debit_list = journal.xpath(".//Debit")
self.assertEqual(6, len(debit_list)) self.assertEqual(6, len(debit_list))
...@@ -341,7 +341,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -341,7 +341,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
journal = journal_list[0] journal = journal_list[0]
ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")]) ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")])
self.assertEqual(['Troisième Écriture'], ecriture_list) self.assertEqual(['Troisieme Ecriture'], ecriture_list)
debit_list = journal.xpath(".//Debit") debit_list = journal.xpath(".//Debit")
self.assertEqual(3, len(debit_list)) self.assertEqual(3, len(debit_list))
...@@ -360,7 +360,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -360,7 +360,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
journal = journal_list[0] journal = journal_list[0]
ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")]) ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")])
self.assertEqual(['Première Écriture'], ecriture_list) self.assertEqual(['Premiere Ecriture'], ecriture_list)
debit_list = journal.xpath(".//Debit") debit_list = journal.xpath(".//Debit")
self.assertEqual(3, len(debit_list)) self.assertEqual(3, len(debit_list))
...@@ -376,7 +376,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -376,7 +376,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
journal = journal_list[0] journal = journal_list[0]
ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")]) ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")])
self.assertEqual(['Seconde Écriture'], ecriture_list) self.assertEqual(['Seconde Ecriture'], ecriture_list)
debit_list = journal.xpath(".//Debit") debit_list = journal.xpath(".//Debit")
self.assertEqual(3, len(debit_list)) self.assertEqual(3, len(debit_list))
...@@ -392,7 +392,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -392,7 +392,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
journal = journal_list[0] journal = journal_list[0]
ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")]) ecriture_list = sorted([x.text.encode('utf-8') for x in journal.xpath(".//EcritureLib")])
self.assertEqual(['Troisième Écriture'], ecriture_list) self.assertEqual(['Troisieme Ecriture'], ecriture_list)
debit_list = journal.xpath(".//Debit") debit_list = journal.xpath(".//Debit")
self.assertEqual(3, len(debit_list)) self.assertEqual(3, len(debit_list))
...@@ -406,7 +406,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -406,7 +406,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
account_module = self.portal.account_module account_module = self.portal.account_module
invoice = self._makeOne( invoice = self._makeOne(
portal_type='Purchase Invoice Transaction', portal_type='Purchase Invoice Transaction',
title='Première Écriture', title='Premiere Ecriture',
simulation_state='delivered', simulation_state='delivered',
reference='1', reference='1',
source_section_value=self.organisation_module.supplier, source_section_value=self.organisation_module.supplier,
...@@ -438,7 +438,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -438,7 +438,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
account_module = self.portal.account_module account_module = self.portal.account_module
self._makeOne( self._makeOne(
portal_type='Purchase Invoice Transaction', portal_type='Purchase Invoice Transaction',
title='Des œufs, des Œufs, des Ÿ et des €', title='Le libéllé c’est çà: œufs, des Œufs, des Ÿ et des €',
simulation_state='delivered', simulation_state='delivered',
reference='1', reference='1',
source_section_value=self.organisation_module.supplier, source_section_value=self.organisation_module.supplier,
...@@ -464,7 +464,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -464,7 +464,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
self.validateFECXML(tree) self.validateFECXML(tree)
self.assertEqual( self.assertEqual(
tree.xpath('//EcritureLib/text()'), tree.xpath('//EcritureLib/text()'),
[u'Des oeufs, des OEufs, des Y et des EUR']) [u'Le libelle cest ca: ufs, des ufs, des Y et des EUR'])
def test_Skip0QuantityLines(self): def test_Skip0QuantityLines(self):
# Don't include lines with 0 quantity in the output, because they are # Don't include lines with 0 quantity in the output, because they are
...@@ -480,6 +480,10 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -480,6 +480,10 @@ class TestAccounting_l10n_fr(AccountingTestCase):
lines=( lines=(
dict( dict(
destination_value=account_module.payable, destination_debit=132.00), destination_value=account_module.payable, destination_debit=132.00),
dict(
destination_value=account_module.payable,
destination_debit=10000.00,
destination_asset_debit=0.00),
dict( dict(
destination_value=account_module.refundable_vat, destination_value=account_module.refundable_vat,
destination_credit=22.00), destination_credit=22.00),
...@@ -499,6 +503,10 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -499,6 +503,10 @@ class TestAccounting_l10n_fr(AccountingTestCase):
start_date=DateTime(2014, 3, 1), start_date=DateTime(2014, 3, 1),
lines=( lines=(
dict(source_value=account_module.receivable, source_debit=240.00), dict(source_value=account_module.receivable, source_debit=240.00),
dict(
source_value=account_module.collected_vat,
source_credit=10000.00,
source_asset_credit=0.00),
dict(source_value=account_module.collected_vat, source_credit=0.00), dict(source_value=account_module.collected_vat, source_credit=0.00),
dict(source_value=account_module.collected_vat, source_credit=40.00), dict(source_value=account_module.collected_vat, source_credit=40.00),
dict(source_value=account_module.goods_sales, source_credit=200.00))) dict(source_value=account_module.goods_sales, source_credit=200.00)))
...@@ -515,6 +523,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -515,6 +523,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
(0.0, 22.0), (0.0, 22.0),
(0.0, 110.0), (0.0, 110.0),
(132.0, 0.0), (132.0, 0.0),
(10000.0, 0.0),
]) ])
self.portal.accounting_module.AccountingTransactionModule_viewFrenchAccountingTransactionFile( self.portal.accounting_module.AccountingTransactionModule_viewFrenchAccountingTransactionFile(
section_category='group/demo_group', section_category='group/demo_group',
...@@ -545,7 +554,7 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -545,7 +554,7 @@ class TestAccounting_l10n_fr(AccountingTestCase):
account_module = self.portal.account_module account_module = self.portal.account_module
invoice = self._makeOne( invoice = self._makeOne(
portal_type='Purchase Invoice Transaction', portal_type='Purchase Invoice Transaction',
title='Première Écriture', title='Premiere Ecriture',
simulation_state='delivered', simulation_state='delivered',
source_section_value=self.organisation_module.supplier, source_section_value=self.organisation_module.supplier,
stop_date=DateTime(2014, 2, 2), stop_date=DateTime(2014, 2, 2),
...@@ -586,6 +595,72 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -586,6 +595,72 @@ class TestAccounting_l10n_fr(AccountingTestCase):
tree.xpath('//EcritureNum/text()'), ['destination_reference']) tree.xpath('//EcritureNum/text()'), ['destination_reference'])
self.assertEqual([n.text for n in tree.xpath('//PieceRef')], [None]) self.assertEqual([n.text for n in tree.xpath('//PieceRef')], [None])
def test_AssetPriceAndQuantityEdgeCase(self):
# Edge case where we have an asset price and quantity of reverse sides.
account_module = self.portal.account_module
self._makeOne(
portal_type='Purchase Invoice Transaction',
title='destination 0',
simulation_state='delivered',
reference='destination',
source_section_value=self.organisation_module.supplier,
stop_date=DateTime(2014, 2, 2),
lines=(
dict(
destination_value=account_module.payable,
destination_debit=100,
destination_asset_credit=123,
),
dict(
destination_value=account_module.goods_purchase,
destination_credit=100,
destination_asset_debit=123,
)))
self._makeOne(
portal_type='Sale Invoice Transaction',
title='source 0',
simulation_state='delivered',
reference='source',
destination_section_value=self.organisation_module.client_2,
start_date=DateTime(2014, 3, 1),
lines=(
dict(
source_value=account_module.receivable,
source_debit=200.00,
source_asset_debit=345,
),
dict(
source_value=account_module.goods_sales,
source_credit=200.00,
source_asset_credit=345,
)))
self.tic()
self.portal.accounting_module.AccountingTransactionModule_viewFrenchAccountingTransactionFile(
section_category='group/demo_group',
section_category_strict=False,
at_date=DateTime(2014, 12, 31),
simulation_state=['delivered'])
self.tic()
tree = etree.fromstring(self.getFECFromMailMessage())
self.validateFECXML(tree)
self.assertEqual(
tree.xpath('//ecriture/PieceRef[text()="destination"]/../ligne/Debit/text()'),
['0.00', '123.00'])
self.assertEqual(
tree.xpath(
'//ecriture/PieceRef[text()="destination"]/../ligne/Credit/text()'),
['123.00', '0.00'])
self.assertEqual(
tree.xpath('//ecriture/PieceRef[text()="source"]/../ligne/Debit/text()'),
['345.00', '0.00'])
self.assertEqual(
tree.xpath(
'//ecriture/PieceRef[text()="source"]/../ligne/Credit/text()'),
['0.00', '345.00'])
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment