diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 93d8a60..de91273 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,10 +7,10 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.7, 3.8, 3.9] - os: [macOs-latest, ubuntu-latest, windows-latest] + python-version: [3.7, 3.8, 3.9, 3.10, 3.11, 3.12] + os: [macos-latest, ubuntu-latest, windows-latest] exclude: - - os: macOs-latest + - os: macos-latest python-version: 3.7 runs-on: ${{ matrix.os }} @@ -28,8 +28,8 @@ jobs: - name: test run: | pip freeze - nosetests --verbosity=3 --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls + pytest - name: Upload coverage uses: codecov/codecov-action@v1 with: - name: ${{ matrix.os }} Python ${{ matrix.python-version }} \ No newline at end of file + name: ${{ matrix.os }} Python ${{ matrix.python-version }} diff --git a/README.rst b/README.rst index 4dbbeae..6ac4e24 100644 --- a/README.rst +++ b/README.rst @@ -380,7 +380,7 @@ and update changelog.yml How to test your contribution ------------------------------ -Although `nose` and `doctest` are both used in code testing, it is adviable that unit tests are put in tests. `doctest` is incorporated only to make sure the code examples in documentation remain valid across different development releases. +Although `pytest` and `doctest` are both used in code testing, it is adviable that unit tests are put in tests. `doctest` is incorporated only to make sure the code examples in documentation remain valid across different development releases. On Linux/Unix systems, please launch your tests like this:: diff --git a/pyexcel_xls/__init__.py b/pyexcel_xls/__init__.py index 5c513bb..b890347 100644 --- a/pyexcel_xls/__init__.py +++ b/pyexcel_xls/__init__.py @@ -7,6 +7,7 @@ :copyright: (c) 2016-2021 by Onni Software Ltd :license: New BSD License """ + import xlrd # flake8: noqa diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index c9f15e8..88fe989 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -7,6 +7,7 @@ :copyright: (c) 2016-2021 by Onni Software Ltd :license: New BSD License """ + import datetime import xlrd diff --git a/pyexcel_xls/xlsw.py b/pyexcel_xls/xlsw.py index f70ec64..bbd2e67 100644 --- a/pyexcel_xls/xlsw.py +++ b/pyexcel_xls/xlsw.py @@ -7,6 +7,7 @@ :copyright: (c) 2016-2021 by Onni Software Ltd :license: New BSD License """ + import datetime import xlrd diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..f731ef4 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = --cov=pyexcel_xls --doctest-glob="*.rst" tests/ README.rst docs/source pyexcel_xls diff --git a/setup.py b/setup.py index 0763a62..6aaddd2 100644 --- a/setup.py +++ b/setup.py @@ -202,7 +202,7 @@ def filter_out_test_code(file_handle): keywords=KEYWORDS, python_requires=PYTHON_REQUIRES, extras_require=EXTRAS_REQUIRE, - tests_require=["nose"], + tests_require=["pytest", "pytest-cov"], install_requires=INSTALL_REQUIRES, packages=PACKAGES, include_package_data=True, diff --git a/test.bat b/test.bat index 823adb3..3387ae9 100644 --- a/test.bat +++ b/test.bat @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls +pytest diff --git a/test.sh b/test.sh index fda8353..9210de0 100644 --- a/test.sh +++ b/test.sh @@ -1,3 +1,3 @@ #/bin/bash pip freeze -nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls +pytest diff --git a/tests/base.py b/tests/base.py index 71474a3..1a8ef6b 100644 --- a/tests/base.py +++ b/tests/base.py @@ -3,8 +3,6 @@ import pyexcel -from nose.tools import eq_, raises # noqa - def create_sample_file1(file): data = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", 1.1, 1] @@ -29,7 +27,7 @@ class PyexcelHatWriterBase: def test_series_table(self): pyexcel.save_as(adict=self.content, dest_file_name=self.testfile) r = pyexcel.get_sheet(file_name=self.testfile, name_columns_by_row=0) - eq_(r.dict, self.content) + assert r.dict == self.content class PyexcelWriterBase: @@ -83,7 +81,7 @@ def test_reading_through_sheets(self): expected = [[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]] assert data == expected data = list(b["Sheet3"].rows()) - expected = [[u"X", u"Y", u"Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]] + expected = [["X", "Y", "Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]] assert data == expected sheet3 = b["Sheet3"] sheet3.name_columns_by_row(0) diff --git a/tests/requirements.txt b/tests/requirements.txt index 3e19c2a..49ec482 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,7 +1,6 @@ -nose +pytest +pytest-cov mock;python_version<"3" -codecov -coverage flake8 black isort diff --git a/tests/requirements3.txt b/tests/requirements3.txt index 4f61832..d730573 100644 --- a/tests/requirements3.txt +++ b/tests/requirements3.txt @@ -1,7 +1,4 @@ lxml pyexcel-ods3 -nose -rednose -nose-cov -codecov -coverage +pytest +pytest-cov diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 85a97dd..89c2464 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -8,15 +8,13 @@ import datetime from unittest.mock import MagicMock, patch +import pytest import pyexcel as pe from _compact import OrderedDict from pyexcel_xls import XLRD_VERSION_2_OR_ABOVE, save_data from pyexcel_xls.xlsr import xldate_to_python_date from pyexcel_xls.xlsw import XLSWriter as Writer -from nose import SkipTest -from nose.tools import eq_, raises - IN_TRAVIS = "TRAVIS" in os.environ @@ -43,15 +41,15 @@ def test_issue_9_hidden_sheet(): test_file = get_fixture("hidden_sheets.xls") book_dict = pe.get_book_dict(file_name=test_file) assert "hidden" not in book_dict - eq_(book_dict["shown"], [["A", "B"]]) + assert book_dict["shown"] == [["A", "B"]] def test_issue_9_hidden_sheet_2(): test_file = get_fixture("hidden_sheets.xls") book_dict = pe.get_book_dict(file_name=test_file, skip_hidden_sheets=False) assert "hidden" in book_dict - eq_(book_dict["shown"], [["A", "B"]]) - eq_(book_dict["hidden"], [["a", "b"]]) + assert book_dict["shown"] == [["A", "B"]] + assert book_dict["hidden"] == [["a", "b"]] def test_issue_10_generator_as_content(): @@ -66,9 +64,9 @@ def custom_row_renderer(row): save_data("test.xls", {"sheet": data_gen()}) -@raises(IOError) def test_issue_13_empty_file_content(): - pe.get_sheet(file_content="", file_type="xls") + with pytest.raises(IOError): + pe.get_sheet(file_content="", file_type="xls") def test_issue_16_file_stream_has_no_getvalue(): @@ -90,7 +88,7 @@ def test_issue_18_encoding_override_isnt_passed(fake_open): def test_issue_20(): if not IN_TRAVIS: - raise SkipTest() + pytest.skip("Must be in CI for this test") pe.get_book( url="https://github.com/pyexcel/pyexcel-xls/raw/master/tests/fixtures/file_with_an_empty_sheet.xls" # noqa: E501 ) @@ -98,28 +96,28 @@ def test_issue_20(): def test_issue_151(): if XLRD_VERSION_2_OR_ABOVE: - raise SkipTest() + pytest.skip("XLRD<2 required for this test") s = pe.get_sheet( file_name=get_fixture("pyexcel_issue_151.xlsx"), skip_hidden_row_and_column=False, library="pyexcel-xls", ) - eq_("#N/A", s[0, 0]) + assert "#N/A" == s[0, 0] -@raises(NotImplementedError) def test_empty_book_pyexcel_issue_120(): """ https://github.com/pyexcel/pyexcel/issues/120 """ - writer = Writer("fake.xls", "xls") - writer.write({}) + with pytest.raises(NotImplementedError): + writer = Writer("fake.xls", "xls") + writer.write({}) def test_pyexcel_issue_54(): xlvalue = 41071.0 date = xldate_to_python_date(xlvalue, 1) - eq_(date, datetime.date(2016, 6, 12)) + assert date == datetime.date(2016, 6, 12) def get_fixture(file_name): diff --git a/tests/test_filter.py b/tests/test_filter.py index cd07d3c..5195362 100644 --- a/tests/test_filter.py +++ b/tests/test_filter.py @@ -2,11 +2,9 @@ from pyexcel_io import get_data, save_data -from nose.tools import eq_ - class TestFilter: - def setUp(self): + def setup_method(self): self.test_file = "test_filter.xls" sample = [ [1, 21, 31], @@ -24,21 +22,21 @@ def test_filter_row(self): self.test_file, start_row=3, library="pyexcel-xls" ) expected = [[4, 24, 34], [5, 25, 35], [6, 26, 36]] - eq_(filtered_data[self.sheet_name], expected) + assert filtered_data[self.sheet_name] == expected def test_filter_row_2(self): filtered_data = get_data( self.test_file, start_row=3, row_limit=1, library="pyexcel-xls" ) expected = [[4, 24, 34]] - eq_(filtered_data[self.sheet_name], expected) + assert filtered_data[self.sheet_name] == expected def test_filter_column(self): filtered_data = get_data( self.test_file, start_column=1, library="pyexcel-xls" ) expected = [[21, 31], [22, 32], [23, 33], [24, 34], [25, 35], [26, 36]] - eq_(filtered_data[self.sheet_name], expected) + assert filtered_data[self.sheet_name] == expected def test_filter_column_2(self): filtered_data = get_data( @@ -48,14 +46,14 @@ def test_filter_column_2(self): library="pyexcel-xls", ) expected = [[21], [22], [23], [24], [25], [26]] - eq_(filtered_data[self.sheet_name], expected) + assert filtered_data[self.sheet_name] == expected def test_filter_both_ways(self): filtered_data = get_data( self.test_file, start_column=1, start_row=3, library="pyexcel-xls" ) expected = [[24, 34], [25, 35], [26, 36]] - eq_(filtered_data[self.sheet_name], expected) + assert filtered_data[self.sheet_name] == expected def test_filter_both_ways_2(self): filtered_data = get_data( @@ -67,7 +65,7 @@ def test_filter_both_ways_2(self): library="pyexcel-xls", ) expected = [[24]] - eq_(filtered_data[self.sheet_name], expected) + assert filtered_data[self.sheet_name] == expected - def tearDown(self): + def teardown_method(self): os.unlink(self.test_file) diff --git a/tests/test_formatters.py b/tests/test_formatters.py index 750a60f..350f3d8 100644 --- a/tests/test_formatters.py +++ b/tests/test_formatters.py @@ -3,8 +3,6 @@ import pyexcel as pe -from nose.tools import eq_ - class TestDateFormat: def test_reading_date_format(self): @@ -22,7 +20,7 @@ def test_reading_date_format(self): library="pyexcel-xls", ) assert isinstance(r[1, 0], datetime.date) - eq_(r[1, 0].strftime("%d/%m/%y"), "25/12/14") + assert r[1, 0].strftime("%d/%m/%y") == "25/12/14" assert isinstance(r[1, 1], datetime.time) is True assert r[1, 1].strftime("%H:%M:%S") == "11:11:11" assert r[4, 0].strftime("%d/%m/%Y") == "01/01/1900" @@ -62,7 +60,7 @@ def test_writing_date_format(self): class TestAutoDetectInt: - def setUp(self): + def setup_method(self): self.content = [[1, 2, 3.1]] self.test_file = "test_auto_detect_init.xls" pe.save_as(array=self.content, dest_file_name=self.test_file) @@ -76,7 +74,7 @@ def test_auto_detect_int(self): | 1 | 2 | 3.1 | +---+---+-----+""" ).strip() - eq_(str(sheet), expected) + assert str(sheet) == expected def test_get_book_auto_detect_int(self): book = pe.get_book(file_name=self.test_file, library="pyexcel-xls") @@ -87,7 +85,7 @@ def test_get_book_auto_detect_int(self): | 1 | 2 | 3.1 | +---+---+-----+""" ).strip() - eq_(str(book), expected) + assert str(book) == expected def test_auto_detect_int_false(self): sheet = pe.get_sheet( @@ -102,7 +100,7 @@ def test_auto_detect_int_false(self): | 1.0 | 2.0 | 3.1 | +-----+-----+-----+""" ).strip() - eq_(str(sheet), expected) + assert str(sheet) == expected def test_get_book_auto_detect_int_false(self): book = pe.get_book( @@ -117,7 +115,7 @@ def test_get_book_auto_detect_int_false(self): | 1.0 | 2.0 | 3.1 | +-----+-----+-----+""" ).strip() - eq_(str(book), expected) + assert str(book) == expected - def tearDown(self): + def teardown_method(self): os.unlink(self.test_file) diff --git a/tests/test_hidden.py b/tests/test_hidden.py index 62d6c29..fcc20a4 100644 --- a/tests/test_hidden.py +++ b/tests/test_hidden.py @@ -2,8 +2,6 @@ from pyexcel_xls import get_data -from nose.tools import eq_ - def test_simple_hidden_sheets(): data = get_data( @@ -11,7 +9,7 @@ def test_simple_hidden_sheets(): skip_hidden_row_and_column=True, ) expected = [[1, 3], [7, 9]] - eq_(data["Sheet1"], expected) + assert data["Sheet1"] == expected def test_complex_hidden_sheets(): @@ -20,4 +18,4 @@ def test_complex_hidden_sheets(): skip_hidden_row_and_column=True, ) expected = [[1, 3, 5, 7, 9], [31, 33, 35, 37, 39], [61, 63, 65, 67]] - eq_(data["Sheet1"], expected) + assert data["Sheet1"] == expected diff --git a/tests/test_merged_cells.py b/tests/test_merged_cells.py index 6f243ac..bfb54c3 100644 --- a/tests/test_merged_cells.py +++ b/tests/test_merged_cells.py @@ -3,8 +3,6 @@ from pyexcel_xls import get_data from pyexcel_xls.xlsr import MergedCell -from nose.tools import eq_ - def test_merged_cells(): data = get_data( @@ -13,7 +11,7 @@ def test_merged_cells(): library="pyexcel-xls", ) expected = [[1, 2, 3], [1, 5, 6], [1, 8, 9], [10, 11, 11]] - eq_(data["Sheet1"], expected) + assert data["Sheet1"] == expected def test_complex_merged_cells(): @@ -32,7 +30,7 @@ def test_complex_merged_cells(): [25, 25, 25, 25, 25, 25, 25, 25, 25, 25], [25, 25, 25, 25, 25, 25, 25, 25, 25, 25], ] - eq_(data["Sheet1"], expected) + assert data["Sheet1"] == expected def test_exploration(): @@ -53,9 +51,9 @@ def test_exploration(): [2], [2], ] - eq_(data["Sheet1"], expected_sheet1) + assert data["Sheet1"] == expected_sheet1 expected_sheet2 = [[3], [3], [3], [3, 4, 4, 4, 4, 4, 4], [3], [3], [3]] - eq_(data["Sheet2"], expected_sheet2) + assert data["Sheet2"] == expected_sheet2 expected_sheet3 = [ ["", "", "", "", "", 2, 2, 2], [], @@ -67,7 +65,7 @@ def test_exploration(): ["", "", "", 5], ["", "", "", 5], ] - eq_(data["Sheet3"], expected_sheet3) + assert data["Sheet3"] == expected_sheet3 def test_merged_cell_class(): @@ -76,8 +74,8 @@ def test_merged_cell_class(): merged_cell.register_cells(test_dict) keys = sorted(list(test_dict.keys())) expected = ["1-1", "1-2", "1-3", "2-1", "2-2", "2-3", "3-1", "3-2", "3-3"] - eq_(keys, expected) - eq_(merged_cell, test_dict["3-1"]) + assert keys == expected + assert merged_cell == test_dict["3-1"] def get_fixture(file_name): diff --git a/tests/test_multiple_sheets.py b/tests/test_multiple_sheets.py index 3f526f7..42b523d 100644 --- a/tests/test_multiple_sheets.py +++ b/tests/test_multiple_sheets.py @@ -1,11 +1,10 @@ import os import sys +import pytest import pyexcel from base import PyexcelMultipleSheetBase -from nose.tools import raises - if sys.version_info[0] == 2 and sys.version_info[1] < 7: from ordereddict import OrderedDict else: @@ -13,13 +12,13 @@ class TestXlsNxlsMultipleSheets(PyexcelMultipleSheetBase): - def setUp(self): + def setup_method(self): self.testfile = "multiple1.xls" self.testfile2 = "multiple1.xls" self.content = _produce_ordered_dict() self._write_test_file(self.testfile) - def tearDown(self): + def teardown_method(self): self._clean_up() @@ -35,7 +34,7 @@ def _write_test_file(self, file): self.rows = 3 pyexcel.save_book_as(bookdict=self.content, dest_file_name=file) - def setUp(self): + def setup_method(self): self.testfile = "multiple1.xls" self.testfile2 = "multiple2.xls" self.testfile3 = "multiple3.xls" @@ -53,13 +52,13 @@ def test_load_a_single_sheet2(self): assert len(b1.sheet_names()) == 1 assert b1["Sheet1"].to_array() == self.content["Sheet1"] - @raises(IndexError) def test_load_a_single_sheet3(self): - pyexcel.get_book(file_name=self.testfile, sheet_index=10000) + with pytest.raises(IndexError): + pyexcel.get_book(file_name=self.testfile, sheet_index=10000) - @raises(ValueError) def test_load_a_single_sheet4(self): - pyexcel.get_book(file_name=self.testfile, sheet_name="Not exist") + with pytest.raises(ValueError): + pyexcel.get_book(file_name=self.testfile, sheet_name="Not exist") def test_delete_sheets(self): b1 = pyexcel.load_book(self.testfile) @@ -208,7 +207,7 @@ def test_add_book_error(self): except TypeError: assert 1 == 1 - def tearDown(self): + def teardown_method(self): if os.path.exists(self.testfile): os.unlink(self.testfile) if os.path.exists(self.testfile2): @@ -216,7 +215,7 @@ def tearDown(self): class TestMultiSheetReader: - def setUp(self): + def setup_method(self): self.testfile = "file_with_an_empty_sheet.xls" def test_reader_with_correct_sheets(self): @@ -231,6 +230,6 @@ def _produce_ordered_dict(): data_dict.update({"Sheet1": [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]}) data_dict.update({"Sheet2": [[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]]}) data_dict.update( - {"Sheet3": [[u"X", u"Y", u"Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]]} + {"Sheet3": [["X", "Y", "Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]]} ) return data_dict diff --git a/tests/test_stringio.py b/tests/test_stringio.py index e1aa055..41a25e5 100644 --- a/tests/test_stringio.py +++ b/tests/test_stringio.py @@ -3,8 +3,6 @@ import pyexcel from base import create_sample_file1 -from nose.tools import eq_ - class TestStringIO: def test_xls_stringio(self): @@ -17,7 +15,7 @@ def test_xls_stringio(self): ) result = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", 1.1, 1] actual = list(r.enumerate()) - eq_(result, actual) + assert result == actual if os.path.exists(testfile): os.unlink(testfile) @@ -29,4 +27,4 @@ def test_xls_output_stringio(self): ) result = [1, 2, 3, 4, 5, 6] actual = list(r.enumerate()) - eq_(result, actual) + assert result == actual diff --git a/tests/test_writer.py b/tests/test_writer.py index 12004e8..79759ce 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -10,7 +10,7 @@ def test_write_book(self): self.content = { "Sheet1": [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], "Sheet2": [[4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6]], - "Sheet3": [[u"X", u"Y", u"Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]], + "Sheet3": [["X", "Y", "Z"], [1, 4, 7], [2, 5, 8], [3, 6, 9]], } self.testfile = "writer.xls" writer = Writer(self.testfile, "xls") @@ -21,17 +21,17 @@ def test_write_book(self): content[key] = list(content[key]) assert content == self.content - def tearDown(self): + def teardown_method(self): if os.path.exists(self.testfile): os.unlink(self.testfile) class TestxlsnCSVWriter(PyexcelWriterBase): - def setUp(self): + def setup_method(self): self.testfile = "test.xls" self.testfile2 = "test.csv" - def tearDown(self): + def teardown_method(self): if os.path.exists(self.testfile): os.unlink(self.testfile) if os.path.exists(self.testfile2): @@ -39,9 +39,9 @@ def tearDown(self): class TestxlsHatWriter(PyexcelHatWriterBase): - def setUp(self): + def setup_method(self): self.testfile = "test.xls" - def tearDown(self): + def teardown_method(self): if os.path.exists(self.testfile): os.unlink(self.testfile)