From 624d248ffd5df58a74ee850bcb3a9051dfc7f521 Mon Sep 17 00:00:00 2001 From: gnzsnz Date: Wed, 29 May 2024 14:35:21 +0200 Subject: [PATCH] Pytest refactor (#3) * tox support - add tox.ini - minor changes to support tox - pyproject clean up * refactor tests - remove boiller plate tests - implement generators to parametrize fixtures - clean up repetitive tests * more refactoring - add xfail marks - run test for CalendarReport as xfail - remove duplicate code from conftest --- .pre-commit-config.yaml | 2 +- ib_fundamental/objects.py | 2 + ib_fundamental/xml_parser.py | 6 + tests/conftest.py | 172 ++++++++++++++++++++++++++ tests/fundamental_data_test.py | 188 ++++------------------------ tests/ib_client_test.py | 41 +++--- tests/xml_parser_test.py | 219 +++++---------------------------- tests/xml_report_test.py | 36 +----- 8 files changed, 256 insertions(+), 410 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 08a1ef4..e6bcd35 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: pylint entry: pyenv which pylint types: [python] - args: [-rn, --rcfile=pyproject.toml] + args: [-rn, --rcfile=pyproject.toml, tests/, ib_fundamental/] - repo: https://github.com/PyCQA/flake8 rev: 7.0.0 hooks: diff --git a/ib_fundamental/objects.py b/ib_fundamental/objects.py index 6374c63..a77d851 100644 --- a/ib_fundamental/objects.py +++ b/ib_fundamental/objects.py @@ -257,6 +257,7 @@ class Revenue: as_of_date: datetime report_type: str period: str + currency: str revenue: float @@ -267,6 +268,7 @@ class EarningsPerShare: as_of_date: datetime report_type: str period: str + currency: str eps: float diff --git a/ib_fundamental/xml_parser.py b/ib_fundamental/xml_parser.py index 90ffd2f..7e033da 100644 --- a/ib_fundamental/xml_parser.py +++ b/ib_fundamental/xml_parser.py @@ -264,11 +264,14 @@ def get_revenue( """Revenue""" fa = "./TotalRevenues" fs = self.xml_report.fin_summary.find(fa) + curr = fs.attrib["currency"] + _revenue = [ Revenue( as_of_date=fromisoformat(tr.attrib["asofDate"]), report_type=tr.attrib["reportType"], period=tr.attrib["period"], + currency=curr, revenue=float(tr.text), ) for tr in fs @@ -290,11 +293,14 @@ def get_eps( """Earnings per share""" fa = "./EPSs" fs = self.xml_report.fin_summary.find(fa) + curr = fs.attrib["currency"] + _eps = [ EarningsPerShare( as_of_date=fromisoformat(tr.attrib["asofDate"]), report_type=tr.attrib["reportType"], period=tr.attrib["period"], + currency=curr, eps=float(tr.text), ) for tr in fs diff --git a/tests/conftest.py b/tests/conftest.py index 47efd8f..c575fd7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,12 +18,23 @@ """IB Fundamental test fixtures""" import os +import typing +from itertools import chain, product, repeat import pytest from ib_async import IB from ib_fundamental.fundamental import FundamentalData from ib_fundamental.ib_client import IBClient +from ib_fundamental.objects import ( + BalanceSheetStatement, + CashFlowStatement, + DividendPerShare, + EarningsPerShare, + IncomeStatement, + ReportType, + Revenue, +) from ib_fundamental.xml_parser import XMLParser from ib_fundamental.xml_report import XMLReport @@ -60,6 +71,66 @@ "WMT", ] +# all but calendar +xml_report_attributes = [ + "fin_statements", + "fin_summary", + "ownership", + "resc", + "snapshot", +] + +statement = [CashFlowStatement, BalanceSheetStatement, IncomeStatement] +stament_period = ["Annual", "Interim"] +statement_period_type = ["annual", "quarter"] + +financials = [DividendPerShare, Revenue, EarningsPerShare] +fin_attrs_parser = ["get_div_per_share", "get_revenue", "get_eps"] +statement_attrs_fun_data = [ + "cashflow_annual", + "cashflow_quarter", + "balance_annual", + "balance_quarter", + "income_annual", + "income_quarter", +] +fin_attrs_fun = [ + "div_ps_ttm", + "div_ps_q", + "revenue_ttm", + "revenue_q", + "eps_ttm", + "eps_q", +] + +report_type = ["TTM", "R"] +period_type = ["12M", "3M"] +forward_year_attrs = ["fy_estimates", "fy_actuals"] +forward_year_parser_attrs = ["get_fy_estimates", "get_fy_actuals"] + +req_report_type = list(typing.get_args(ReportType)) + +map_items_statement_type = ["CAS", "BAL", "INC"] + + +def repeat_each(iterable, n=2): + """Repeat each element in *iterable* *n* times. + + >>> list(repeat_each('ABC', 3)) + ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'] + """ + return chain.from_iterable(map(repeat, iterable, repeat(n))) + + +def ncycles(iterable, n): + """Returns the sequence elements *n* times + + >>> list(ncycles(["a", "b"], 3)) + ['a', 'b', 'a', 'b', 'a', 'b'] + + """ + return chain.from_iterable(repeat(tuple(iterable), n)) + @pytest.fixture(scope="session") def tws_client(): @@ -83,6 +154,13 @@ def ib_client(tws_client, request): del _ib_client +@pytest.fixture(scope="function", params=req_report_type) +def ib_client_req_fund(ib_client, request): + """IBClient ib_req_fund combinations""" + _report = request.param + yield ib_client.ib_req_fund(_report) + + @pytest.fixture(scope="class") def xml_report(ib_client): """XMLReport fixture""" @@ -92,6 +170,13 @@ def xml_report(ib_client): del _xml_report +@pytest.fixture(scope="function", params=xml_report_attributes) +def xml_report_attrs(xml_report, request): + """XMLReport get attributes""" + _attr = request.param + yield getattr(xml_report, _attr) + + @pytest.fixture(scope="function") def xml_parser(ib_client): """XMLReport fixture""" @@ -101,6 +186,54 @@ def xml_parser(ib_client): del _xml_parser +gen_parser_statement = ( + (*_m, *_p) + for _m in zip(map_items_statement_type, statement) + for _p in zip(stament_period, statement_period_type) +) + + +@pytest.fixture(scope="function", params=gen_parser_statement) +def xml_parser_statement(xml_parser, request): + """XMLParser statement combinations""" + _statement_type, _statement, _stament_period, _statement_period_type = request.param + _parser_statement = xml_parser.get_fin_statement( + _statement_type, _statement_period_type + ) + yield _parser_statement, _statement, _stament_period + + +@pytest.fixture(scope="function", params=map_items_statement_type) +def xml_parser_map_items(xml_parser, request): + """XMLParser map_items statement type combinations""" + _statement_type = request.param + _map_items = xml_parser.get_map_items(_statement_type) + yield _map_items, _statement_type + + +gen_parser_fin = ( + (*_f, *_t) + for _f in zip(financials, fin_attrs_parser) + for _t in zip(report_type, period_type) +) + + +@pytest.fixture(scope="function", params=gen_parser_fin) +def xml_parser_financials(xml_parser, request): + """XMLParser div ps, rev, eps combinations""" + _financials, _fin_attrs_parser, _report_type, _period_type = request.param + _fin = getattr(xml_parser, _fin_attrs_parser)(_report_type, _period_type) + yield _financials, _fin, _report_type, _period_type + + +@pytest.fixture(scope="function", params=forward_year_parser_attrs) +def xml_parser_fy(xml_parser, request): + """XMLParser fy estimates and actuals""" + _attr = request.param + _fy = getattr(xml_parser, _attr)() + yield _fy + + @pytest.fixture(scope="class", params=DJIA) def fundamental_data(tws_client, request): """FundamentalData fixture""" @@ -109,3 +242,42 @@ def fundamental_data(tws_client, request): _fund = FundamentalData(symbol=_symbol, ib=_tws_client) yield _fund del _fund + + +gen_fund_statement = ( + (a, *b) + for a, b in zip(statement_attrs_fun_data, product(statement, stament_period)) +) + + +@pytest.fixture(scope="function", params=gen_fund_statement) +def fundamental_statement(fundamental_data, request): + """FundamentalData statements""" + _attr, _class, _period = request.param + _statement = getattr(fundamental_data, _attr) + yield _statement, _class, _period + + +gen_financials = ( + (_class, _attr, *_t) + for _class, _attr, _t in zip( + repeat_each(financials, 2), + fin_attrs_fun, + ncycles(zip(report_type, period_type), 3), + ) +) + + +@pytest.fixture(scope="function", params=gen_financials) +def fundamental_financials(fundamental_data, request): + """FundamentalData financials""" + _class, _attr, _report_type, _period_type = request.param + yield getattr(fundamental_data, _attr), _class, _report_type, _period_type + + +@pytest.fixture(scope="function", params=forward_year_attrs) +def fundamental_fy(fundamental_data, request): + """FundamentalData fy estimates and actuals""" + _attr = request.param + _fy = getattr(fundamental_data, _attr) + yield _fy diff --git a/tests/fundamental_data_test.py b/tests/fundamental_data_test.py index a885c87..58dbc1c 100644 --- a/tests/fundamental_data_test.py +++ b/tests/fundamental_data_test.py @@ -16,96 +16,35 @@ # under the License. """Test fundamental FundamentalData module""" - +import pytest from ib_async import Dividends, FundamentalRatios, Ticker from ib_fundamental.fundamental import FundamentalData from ib_fundamental.objects import ( AnalystForecast, - BalanceSheetStatement, - CashFlowStatement, CompanyInfo, Dividend, - DividendPerShare, - EarningsPerShare, ForwardYear, - IncomeStatement, OwnershipCompany, OwnershipDetails, OwnershipReport, RatioSnapshot, - Revenue, ) class TestFundamentalData: """Test FundamentalData class""" - def test_statement_inc_annual(self, fundamental_data: FundamentalData): - """Test FundamentalData annual income statement""" - # act - _fund_data = fundamental_data - _inc = _fund_data.income_annual - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], IncomeStatement) - assert _inc[0].period == "Annual" - - def test_statement_inc_quarter(self, fundamental_data: FundamentalData): - """Test FundamentalData quarter income statement""" - # act - _fund_data = fundamental_data - _inc = _fund_data.income_quarter - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], IncomeStatement) - assert _inc[0].period == "Interim" - - def test_statement_bal_annual(self, fundamental_data: FundamentalData): - """Test FundamentalData annual balance sheet""" - # act - _fund_data = fundamental_data - _inc = _fund_data.balance_annual - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], BalanceSheetStatement) - assert _inc[0].period == "Annual" - - def test_statement_bal_quarter(self, fundamental_data: FundamentalData): - """Test FundamentalData balance sheet quarter""" - # act - _fund_data = fundamental_data - _inc = _fund_data.balance_quarter + def test_statments(self, fundamental_statement): + """Test FundamentalData statements, income, cashflow, balance sheet + by period, Annual and Interim + """ + _statement, _class, _period = fundamental_statement # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], BalanceSheetStatement) - assert _inc[0].period == "Interim" - - def test_statement_cas_annual(self, fundamental_data: FundamentalData): - """Test FundamentalData annual cashflow""" - # act - _fund_data = fundamental_data - _inc = _fund_data.cashflow_annual - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], CashFlowStatement) - assert _inc[0].period == "Annual" - - def test_statement_cas_quarter(self, fundamental_data: FundamentalData): - """Test FundamentalData cashflow quarter""" - # act - _fund_data = fundamental_data - _inc = _fund_data.cashflow_quarter - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], CashFlowStatement) - assert _inc[0].period == "Interim" + assert isinstance(_statement, list) + assert len(_statement) > 1 + assert isinstance(_statement[0], _class) + assert _statement[0].period == _period def test_ownership(self, fundamental_data: FundamentalData): """Test FundamentalData ownership report""" @@ -119,6 +58,7 @@ def test_ownership(self, fundamental_data: FundamentalData): assert len(_own.ownership_details) > 1 assert isinstance(_own.ownership_details[0], OwnershipDetails) + @pytest.mark.xfail(reason="Non dividend paying companies will fail") def test_dividend(self, fundamental_data: FundamentalData): """Test FundamentalData dividends""" # act @@ -138,79 +78,17 @@ def test_dividend_summary(self, fundamental_data: FundamentalData): # assert assert isinstance(_div_summary, Dividends) - def test_div_per_share_ttm(self, fundamental_data: FundamentalData): - """Test XMLparser div per share TTM""" - # act - _fund_data = fundamental_data - _divps = _fund_data.div_ps_ttm + @pytest.mark.xfail(reason="Non dividend paying companies will fail") + def test_financials(self, fundamental_financials): + """Test FundamentalData financials, dividends per share, revenue,eps""" + _fin, _class, _report_type, _period_type = fundamental_financials # assert - assert isinstance(_divps, list) - assert len(_divps) > 1 - assert isinstance(_divps[0], DividendPerShare) - assert _divps[0].report_type == "TTM" - assert _divps[0].period == "12M" - assert _divps[0].currency == "USD" - - def test_div_per_share_q(self, fundamental_data: FundamentalData): - """Test XMLparser div per share quarter""" - # act - _fund_data = fundamental_data - _divps = _fund_data.div_ps_q - # assert - assert isinstance(_divps, list) - assert len(_divps) > 1 - assert isinstance(_divps[0], DividendPerShare) - assert _divps[0].report_type == "R" - assert _divps[0].period == "3M" - assert _divps[0].currency == "USD" - - def test_revenue_ttm(self, fundamental_data: FundamentalData): - """Test XMLparser revenue ttm""" - # act - _fund_data = fundamental_data - _rev = _fund_data.revenue_ttm - # assert - assert isinstance(_rev, list) - assert len(_rev) > 1 - assert isinstance(_rev[0], Revenue) - assert _rev[0].report_type == "TTM" - assert _rev[0].period == "12M" - - def test_revenue_q(self, fundamental_data: FundamentalData): - """Test XMLparser revenue quarter""" - # act - _fund_data = fundamental_data - _rev = _fund_data.revenue_q - # assert - assert isinstance(_rev, list) - assert len(_rev) > 1 - assert isinstance(_rev[0], Revenue) - assert _rev[0].report_type == "R" - assert _rev[0].period == "3M" - - def test_eps_ttm(self, fundamental_data: FundamentalData): - """Test XMLparser eps ttm""" - # act - _fund_data = fundamental_data - _eps = _fund_data.eps_ttm - # assert - assert isinstance(_eps, list) - assert len(_eps) > 1 - assert isinstance(_eps[0], EarningsPerShare) - assert _eps[0].report_type == "TTM" - assert _eps[0].period == "12M" - - def test_eps_q(self, fundamental_data: FundamentalData): - """Test XMLparser eps quarter""" - # act - _fund_data = fundamental_data - _eps = _fund_data.eps_q - # assert - assert isinstance(_eps, list) - assert len(_eps) > 1 - assert isinstance(_eps[0], EarningsPerShare) - assert _eps[0].report_type == "R" - assert _eps[0].period == "3M" + assert isinstance(_fin, list) + assert len(_fin) > 1 + assert isinstance(_fin[0], _class) + assert _fin[0].report_type == _report_type + assert _fin[0].period == _period_type + assert _fin[0].currency == "USD" def test_analyst_forecast(self, fundamental_data: FundamentalData): """Test FundamentalData analyst forecast""" @@ -243,25 +121,13 @@ def test_fundamental_rations(self, fundamental_data: FundamentalData): assert hasattr(_fund_data, "ticker") assert isinstance(_fund_data.ticker, Ticker) - def test_fy_estimates(self, fundamental_data: FundamentalData): - """Test FundamentalData fy estimates""" - # act - _fund_data = fundamental_data - _estimates = _fund_data.fy_estimates - # assert - assert isinstance(_estimates, list) - assert len(_estimates) > 1 - assert isinstance(_estimates[0], ForwardYear) - - def test_fy_actuals(self, fundamental_data: FundamentalData): - """Test FundamentalData fy actuals""" - # act - _fund_data = fundamental_data - _actuals = _fund_data.fy_actuals + def test_forward_year(self, fundamental_fy): + """Test FundamentalData fy estimates and actuals""" + _fy = fundamental_fy # assert - assert isinstance(_actuals, list) - assert len(_actuals) > 1 - assert isinstance(_actuals[0], ForwardYear) + assert isinstance(_fy, list) + assert len(_fy) > 1 + assert isinstance(_fy[0], ForwardYear) def test_company_info(self, fundamental_data: FundamentalData): """Test FundamentalData company info""" diff --git a/tests/ib_client_test.py b/tests/ib_client_test.py index 5504a85..90a88c1 100644 --- a/tests/ib_client_test.py +++ b/tests/ib_client_test.py @@ -26,28 +26,29 @@ class TestIBClient: + """Test class for IBClient""" - def test_instantiation(self, ib_client: IBClient): + def test_instantiation(self, ib_client): """test IBClient instance""" # assert assert isinstance(ib_client, IBClient) assert isinstance(ib_client.ib, IB) assert ib_client.is_connected() - def test_make_contract(self, ib_client: IBClient): + def test_make_contract(self, ib_client): """test IBClient.contract is correct""" # assert assert isinstance(ib_client.contract, Stock) assert ib_client.contract.symbol == ib_client.symbol - def test_ratios(self, ib_client: IBClient): + def test_ratios(self, ib_client): """Test FundamentalRatios""" # act _ratio = ib_client.get_ratios() # assert assert isinstance(_ratio, FundamentalRatios) - def test_ticker(self, ib_client: IBClient): + def test_ticker(self, ib_client): """Test IBClient.ticker""" # arrange _ticker = ib_client.get_ticker() @@ -58,42 +59,28 @@ def test_ticker(self, ib_client: IBClient): assert isinstance(_ticker, Ticker) assert _ticker.contract == ib_client.contract - def test_req_fundamental(self, ib_client: IBClient): + @pytest.mark.xfail(reason="CalendarReport requires subscription") + def test_req_fundamental(self, ib_client_req_fund): """Test IBClient.ib_req_fund""" # arrange - _report_type = [ - "ReportsFinStatements", - "ReportsFinSummary", - "ReportSnapshot", - "RESC", - "ReportsOwnership", - ] - _reports = [ib_client.ib_req_fund(_r) for _r in _report_type] + _report = ib_client_req_fund # assert - assert len(_reports) == 5 - assert all([isinstance(_r, str) for _r in _reports]) + assert isinstance(_report, str) - def test_req_fundamental_error(self, ib_client: IBClient): + def test_req_fundamental_error(self, ib_client): """Test IBClient.ib_req_fund raises ValueError""" # arrange - _report_type = [ - "ReportsFinStatements", - "ReportsFinSummary", - "ReportSnapshot", - "RESC", - "ReportsOwnership", - "CalendarReport", - ] + _report_type = "CalendarReport" with pytest.raises(ValueError) as ex_info: - _ = [ib_client.ib_req_fund(_r) for _r in _report_type] + _ = ib_client.ib_req_fund(_report_type) # assert assert ex_info.type is ValueError - def test_is_connected(self, ib_client: IBClient): + def test_is_connected(self, ib_client): """Test IBClient.is_connected""" assert ib_client.is_connected() - def test_disconnect(self, ib_client: IBClient): + def test_disconnect(self, ib_client): """Test IBClient.disconnect""" # act ib_client.disconnect() diff --git a/tests/xml_parser_test.py b/tests/xml_parser_test.py index 4ad674c..f4946f8 100644 --- a/tests/xml_parser_test.py +++ b/tests/xml_parser_test.py @@ -17,21 +17,17 @@ """Test xml_parser module""" +import pytest + from ib_fundamental.objects import ( AnalystForecast, - BalanceSheetStatement, - CashFlowStatement, CompanyInfo, Dividend, - DividendPerShare, - EarningsPerShare, ForwardYear, - IncomeStatement, OwnershipCompany, OwnershipDetails, OwnershipReport, RatioSnapshot, - Revenue, StatementMap, ) from ib_fundamental.xml_parser import XMLParser @@ -40,102 +36,19 @@ class TestXMLParser: """Test XMLParser class""" - def test_statement_inc_annual(self, xml_parser: XMLParser): - """Test XMLParser annual income statement""" - # act - _xml_parser = xml_parser - _inc = _xml_parser.get_fin_statement(statement="INC") - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], IncomeStatement) - assert _inc[0].period == "Annual" - - def test_statement_inc_quarter(self, xml_parser: XMLParser): - """Test XMLParser quarter income statement""" - # act - _xml_parser = xml_parser - _inc = _xml_parser.get_fin_statement(statement="INC", period="quarter") - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], IncomeStatement) - assert _inc[0].period == "Interim" - - def test_statement_bal_annual(self, xml_parser: XMLParser): - """Test XMLParser annual balance sheet""" - # act - _xml_parser = xml_parser - _inc = _xml_parser.get_fin_statement(statement="BAL") - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], BalanceSheetStatement) - assert _inc[0].period == "Annual" - - def test_statement_bal_quarter(self, xml_parser: XMLParser): - """Test XMLParser balance sheet quarter""" - # act - _xml_parser = xml_parser - _inc = _xml_parser.get_fin_statement(statement="BAL", period="quarter") - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], BalanceSheetStatement) - assert _inc[0].period == "Interim" - - def test_statement_cas_annual(self, xml_parser: XMLParser): - """Test XMLParser annual cashflow""" - # act - _xml_parser = xml_parser - _inc = _xml_parser.get_fin_statement(statement="CAS") - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], CashFlowStatement) - assert _inc[0].period == "Annual" - - def test_statement_cas_quarter(self, xml_parser: XMLParser): - """Test XMLParser cashflow quarter""" - # act - _xml_parser = xml_parser - _inc = _xml_parser.get_fin_statement(statement="CAS", period="quarter") - # assert - assert isinstance(_inc, list) - assert len(_inc) > 1 - assert isinstance(_inc[0], CashFlowStatement) - assert _inc[0].period == "Interim" - - def test_map_items_bal(self, xml_parser: XMLParser): - """Test XMLParser map_items balance sheet""" - # act - _xml_parser = xml_parser - _statement = "BAL" - _map_items = _xml_parser.get_map_items(statement=_statement) - # assert - assert isinstance(_map_items, list) - assert len(_map_items) > 1 - assert isinstance(_map_items[0], StatementMap) - assert _map_items[0].statement_type == _statement - - def test_map_items_cas(self, xml_parser: XMLParser): - """Test XMLParser map_items cashflow""" - # act - _xml_parser = xml_parser - _statement = "CAS" - _map_items = _xml_parser.get_map_items(statement=_statement) + def test_statement(self, xml_parser_statement): + """Test XML Parser statements""" + _parser_statement, _statement, _period = xml_parser_statement + print(_parser_statement, _statement, _period) # assert - assert isinstance(_map_items, list) - assert len(_map_items) > 1 - assert isinstance(_map_items[0], StatementMap) - assert _map_items[0].statement_type == _statement + assert isinstance(_parser_statement, list) + assert len(_parser_statement) > 1 + assert isinstance(_parser_statement[0], _statement) + assert _parser_statement[0].period == _period - def test_map_items_inc(self, xml_parser: XMLParser): - """Test XMLParser map_items income""" - # act - _xml_parser = xml_parser - _statement = "INC" - _map_items = _xml_parser.get_map_items(statement=_statement) + def test_map_items(self, xml_parser_map_items): + """Test XML Parser map_items""" + _map_items, _statement = xml_parser_map_items # assert assert isinstance(_map_items, list) assert len(_map_items) > 1 @@ -154,6 +67,7 @@ def test_ownership(self, xml_parser: XMLParser): assert len(_own.ownership_details) > 1 assert isinstance(_own.ownership_details[0], OwnershipDetails) + @pytest.mark.xfail(reason="Non dividend paying companies will fail") def test_dividen(self, xml_parser: XMLParser): """Test XMLParser dividends""" # act @@ -165,79 +79,18 @@ def test_dividen(self, xml_parser: XMLParser): assert isinstance(_div[0], Dividend) assert _div[0].currency == "USD" - def test_div_per_share_ttm(self, xml_parser: XMLParser): - """Test XMLparser div per share TTM""" - # act - _xml_parser = xml_parser - _divps = _xml_parser.get_div_per_share(report_type="TTM") - # assert - assert isinstance(_divps, list) - assert len(_divps) > 1 - assert isinstance(_divps[0], DividendPerShare) - assert _divps[0].report_type == "TTM" - assert _divps[0].period == "12M" - assert _divps[0].currency == "USD" - - def test_div_per_share_q(self, xml_parser: XMLParser): - """Test XMLparser div per share quarter""" - # act - _xml_parser = xml_parser - _divps = _xml_parser.get_div_per_share(report_type="R", period="3M") - # assert - assert isinstance(_divps, list) - assert len(_divps) > 1 - assert isinstance(_divps[0], DividendPerShare) - assert _divps[0].report_type == "R" - assert _divps[0].period == "3M" - assert _divps[0].currency == "USD" - - def test_revenue_ttm(self, xml_parser: XMLParser): - """Test XMLparser revenue ttm""" - # act - _xml_parser = xml_parser - _rev = _xml_parser.get_revenue(report_type="TTM") - # assert - assert isinstance(_rev, list) - assert len(_rev) > 1 - assert isinstance(_rev[0], Revenue) - assert _rev[0].report_type == "TTM" - assert _rev[0].period == "12M" - - def test_revenue_q(self, xml_parser: XMLParser): - """Test XMLparser revenue quarter""" + @pytest.mark.xfail(reason="Non dividend paying companies will fail") + def test_financials(self, xml_parser_financials): + """Test XMLParser div ps, revenue, eps""" # act - _xml_parser = xml_parser - _rev = _xml_parser.get_revenue(report_type="R", period="3M") + _financials, _fin, _report_type, _period_type = xml_parser_financials # assert - assert isinstance(_rev, list) - assert len(_rev) > 1 - assert isinstance(_rev[0], Revenue) - assert _rev[0].report_type == "R" - assert _rev[0].period == "3M" - - def test_eps_ttm(self, xml_parser: XMLParser): - """Test XMLparser eps ttm""" - # act - _xml_parser = xml_parser - _eps = _xml_parser.get_eps(report_type="TTM") - # assert - assert isinstance(_eps, list) - assert len(_eps) > 1 - assert isinstance(_eps[0], EarningsPerShare) - assert _eps[0].report_type == "TTM" - assert _eps[0].period == "12M" - - def test_eps_q(self, xml_parser: XMLParser): - """Test XMLparser eps quarter""" - # act - _xml_parser = xml_parser - _eps = _xml_parser.get_eps(report_type="R", period="3M") - # assert - assert isinstance(_eps, list) - assert len(_eps) > 1 - assert isinstance(_eps[0], EarningsPerShare) - assert _eps[0].report_type == "R" - assert _eps[0].period == "3M" + assert isinstance(_fin, list) + assert len(_fin) > 1 + assert isinstance(_fin[0], _financials) + assert _fin[0].report_type == _report_type + assert _fin[0].period == _period_type + assert _fin[0].currency == "USD" def test_analyst_forecast(self, xml_parser: XMLParser): """Test XMLParser analyst forecast""" @@ -260,25 +113,13 @@ def test_ratios(self, xml_parser: XMLParser): assert isinstance(_ratios, RatioSnapshot) assert hasattr(_ratios, "ttmrev") - def test_fy_estimates(self, xml_parser: XMLParser): - """Test XMLParser fy estimates""" - # act - _xml_parser = xml_parser - _estimates = _xml_parser.get_fy_estimates() - # assert - assert isinstance(_estimates, list) - assert len(_estimates) > 1 - assert isinstance(_estimates[0], ForwardYear) - - def test_fy_actuals(self, xml_parser: XMLParser): - """Test XMLParser fy actuals""" - # act - _xml_parser = xml_parser - _actuals = _xml_parser.get_fy_actuals() + def test_forward_year(self, xml_parser_fy): + """Test XMLParser fy estimates & actuals""" + _fy = xml_parser_fy # assert - assert isinstance(_actuals, list) - assert len(_actuals) > 1 - assert isinstance(_actuals[0], ForwardYear) + assert isinstance(_fy, list) + assert len(_fy) > 1 + assert isinstance(_fy[0], ForwardYear) def test_company_info(self, xml_parser: XMLParser): """Test XMLParser company info""" diff --git a/tests/xml_report_test.py b/tests/xml_report_test.py index bfa6c59..2165db8 100644 --- a/tests/xml_report_test.py +++ b/tests/xml_report_test.py @@ -34,40 +34,12 @@ def test_instantiation(self, xml_report): assert isinstance(_report, XMLReport) assert isinstance(_report.client, IBClient) - def test_fin_statement(self, xml_report): - """Test XMLReport.fin_statement""" + def test_xml_report_property(self, xml_report_attrs): + """Test XMLReport properties""" # act - _statement = xml_report.fin_statements + _attr = xml_report_attrs # assert - assert isinstance(_statement, Element) - - def test_fin_summary(self, xml_report): - """Test XMLReport.fin_summary""" - # act - _statement = xml_report.fin_summary - # assert - assert isinstance(_statement, Element) - - def test_snapshot(self, xml_report): - """Test XMLReport.snapshot""" - # act - _statement = xml_report.snapshot - # assert - assert isinstance(_statement, Element) - - def test_ownership(self, xml_report): - """Test XMLReport.ownership""" - # act - _statement = xml_report.ownership - # assert - assert isinstance(_statement, Element) - - def test_resc(self, xml_report): - """Test XMLReport.rest""" - # act - _statement = xml_report.resc - # assert - assert isinstance(_statement, Element) + assert isinstance(_attr, Element) def test_calendar(self, xml_report): """Test XMLReport.calendar"""