From 1debdf07eeb623fb7c2f9d6c956f8a099297f1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20W=C3=BCrl?= Date: Fri, 14 Nov 2025 14:47:05 +0100 Subject: [PATCH 1/5] add tests in progress --- tests/builder/test_builder_strike.py | 260 +++++++++++++++++++++++ tests/dataimport/test_dataimport_base.py | 255 ++++++++++++++++++++++ tests/db/test_db_table.py | 147 +++++++++++++ 3 files changed, 662 insertions(+) create mode 100644 tests/builder/test_builder_strike.py create mode 100644 tests/dataimport/test_dataimport_base.py create mode 100644 tests/db/test_db_table.py diff --git a/tests/builder/test_builder_strike.py b/tests/builder/test_builder_strike.py new file mode 100644 index 0000000..f7256b0 --- /dev/null +++ b/tests/builder/test_builder_strike.py @@ -0,0 +1,260 @@ +# -*- coding: utf8 -*- + +""" + +Copyright 2014-2016 Andreas Würl + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +""" + +import datetime + +from assertpy import assert_that # pylint: disable=import-error +import pytest # pylint: disable=import-error + +import blitzortung.builder.strike +import blitzortung.builder.base +import blitzortung.data + + +class TestStrikeBuilder: + """Test suite for Strike builder class.""" + + def test_strike_inherits_from_event(self): + """Test that Strike inherits from Event.""" + assert_that( + issubclass( + blitzortung.builder.strike.Strike, blitzortung.builder.base.Event + ) + ).is_true() + + def test_strike_initialization(self): + """Test Strike initializes with default values.""" + strike = blitzortung.builder.strike.Strike() + assert_that(strike.id_value).is_equal_to(-1) + assert_that(strike.altitude).is_none() + assert_that(strike.amplitude).is_none() + assert_that(strike.lateral_error).is_none() + assert_that(strike.station_count).is_none() + assert_that(strike.stations).is_equal_to([]) + + def test_position_parser_regex(self): + """Test that position parser regex is defined.""" + parser = blitzortung.builder.strike.Strike.position_parser + assert_that(parser).is_not_none() + # Test parsing + match = parser.findall("pos;-5.2;10.3;200.5") + assert_that(match).is_length(1) + assert_that(match[0]).is_equal_to(("-5.2", "10.3", "200.5")) + + def test_amplitude_parser_regex(self): + """Test that amplitude parser regex is defined.""" + parser = blitzortung.builder.strike.Strike.amplitude_parser + assert_that(parser).is_not_none() + match = parser.findall("str;45.3") + assert_that(match).is_equal_to(["45.3"]) + + def test_deviation_parser_regex(self): + """Test that deviation parser regex is defined.""" + parser = blitzortung.builder.strike.Strike.deviation_parser + assert_that(parser).is_not_none() + match = parser.findall("dev;123.45") + assert_that(match).is_equal_to(["123.45"]) + + def test_stations_parser_regex(self): + """Test that stations parser regex is defined.""" + parser = blitzortung.builder.strike.Strike.stations_parser + assert_that(parser).is_not_none() + match = parser.findall("sta;5;10;1,2,3,4,5") + assert_that(match).is_length(1) + assert_that(match[0]).is_equal_to(("5", "10", "1,2,3,4,5")) + + def test_set_id(self): + """Test setting strike id.""" + strike = blitzortung.builder.strike.Strike() + result = strike.set_id(12345) + assert_that(result).is_equal_to(strike) # Returns self + assert_that(strike.id_value).is_equal_to(12345) + + def test_set_altitude(self): + """Test setting altitude.""" + strike = blitzortung.builder.strike.Strike() + result = strike.set_altitude(1500.5) + assert_that(result).is_equal_to(strike) + assert_that(strike.altitude).is_equal_to(1500.5) + + def test_set_amplitude(self): + """Test setting amplitude.""" + strike = blitzortung.builder.strike.Strike() + result = strike.set_amplitude(42.3) + assert_that(result).is_equal_to(strike) + assert_that(strike.amplitude).is_equal_to(42.3) + + def test_set_lateral_error(self): + """Test setting lateral error.""" + strike = blitzortung.builder.strike.Strike() + result = strike.set_lateral_error(500.0) + assert_that(result).is_equal_to(strike) + # Should be clamped to 0-32767 range + assert_that(strike.lateral_error).is_greater_than_or_equal_to(0) + assert_that(strike.lateral_error).is_less_than_or_equal_to(32767) + + def test_set_lateral_error_clamping_lower(self): + """Test that lateral error is clamped to minimum 0.""" + strike = blitzortung.builder.strike.Strike() + strike.set_lateral_error(-100.0) + assert_that(strike.lateral_error).is_equal_to(0) + + def test_set_lateral_error_clamping_upper(self): + """Test that lateral error is clamped to maximum 32767.""" + strike = blitzortung.builder.strike.Strike() + strike.set_lateral_error(100000.0) + assert_that(strike.lateral_error).is_equal_to(32767) + + def test_set_station_count(self): + """Test setting station count.""" + strike = blitzortung.builder.strike.Strike() + result = strike.set_station_count(15) + assert_that(result).is_equal_to(strike) + assert_that(strike.station_count).is_equal_to(15) + + def test_set_stations(self): + """Test setting stations list.""" + strike = blitzortung.builder.strike.Strike() + stations = [1, 2, 3, 4, 5] + result = strike.set_stations(stations) + assert_that(result).is_equal_to(strike) + assert_that(strike.stations).is_equal_to(stations) + + def test_method_chaining(self): + """Test that methods can be chained.""" + strike = blitzortung.builder.strike.Strike() + result = ( + strike.set_id(1).set_altitude(1000).set_amplitude(50).set_station_count(10) + ) + assert_that(result).is_same_as(strike) + assert_that(strike.id_value).is_equal_to(1) + assert_that(strike.altitude).is_equal_to(1000) + assert_that(strike.amplitude).is_equal_to(50) + assert_that(strike.station_count).is_equal_to(10) + + def test_from_line_with_valid_data(self): + """Test parsing strike from valid data line.""" + strike = blitzortung.builder.strike.Strike() + # Example line format with all required fields + line = "2025-01-15T12:30:45.123456+00:00 pos;48.5;-10.2;500.5 str;45.2 dev;250.0 sta;5;10;1,2,3,4,5" + + result = strike.from_line(line) + assert_that(result).is_same_as(strike) + assert_that(strike.x_coord).is_equal_to(-10.2) + assert_that(strike.y_coord).is_equal_to(48.5) + assert_that(strike.altitude).is_equal_to(500.5) + assert_that(strike.amplitude).is_equal_to(45.2) + assert_that(strike.lateral_error).is_equal_to(250) + assert_that(strike.station_count).is_equal_to(5) + assert_that(strike.stations).is_equal_to([1, 2, 3, 4, 5]) + + def test_from_line_with_missing_stations(self): + """Test parsing strike with missing stations in list.""" + strike = blitzortung.builder.strike.Strike() + line = "2025-01-15T12:30:45.123456+00:00 pos;48.5;-10.2;500.5 str;45.2 dev;250.0 sta;3;10;1,,3" + + result = strike.from_line(line) + assert_that(result).is_same_as(strike) + # Empty string should be filtered out + assert_that(strike.stations).is_equal_to([1, 3]) + + def test_from_line_with_no_stations(self): + """Test parsing strike with empty stations list.""" + strike = blitzortung.builder.strike.Strike() + line = "2025-01-15T12:30:45.123456+00:00 pos;48.5;-10.2;500.5 str;45.2 dev;250.0 sta;0;10;" + + result = strike.from_line(line) + assert_that(strike.stations).is_equal_to([]) + + def test_from_line_with_invalid_format_raises_error(self): + """Test that invalid line format raises BuilderError.""" + strike = blitzortung.builder.strike.Strike() + line = "invalid line format" + + with pytest.raises(blitzortung.builder.base.BuilderError): + strike.from_line(line) + + def test_from_line_with_missing_position_raises_error(self): + """Test that missing position raises BuilderError.""" + strike = blitzortung.builder.strike.Strike() + line = "2025-01-15T12:30:45.123456+00:00 str;45.2 dev;250.0 sta;5;10;1,2,3" + + with pytest.raises(blitzortung.builder.base.BuilderError): + strike.from_line(line) + + def test_from_line_with_invalid_float_raises_error(self): + """Test that non-numeric values raise BuilderError.""" + strike = blitzortung.builder.strike.Strike() + line = "2025-01-15T12:30:45.123456+00:00 pos;invalid;-10.2;500.5 str;45.2 dev;250.0 sta;5;10;1,2,3" + + with pytest.raises(blitzortung.builder.base.BuilderError): + strike.from_line(line) + + def test_build_returns_strike_object(self): + """Test that build returns data.Strike object.""" + strike = blitzortung.builder.strike.Strike() + dt = datetime.datetime.now(datetime.timezone.utc) + strike.set_timestamp(dt).set_id(100).set_x(5.5).set_y(10.2).set_altitude(1000) + strike.set_amplitude(50.5).set_lateral_error(250).set_station_count(5) + + result = strike.build() + assert_that(result).is_instance_of(blitzortung.data.Strike) + + def test_build_with_complete_data(self): + """Test building strike with all data set.""" + strike = blitzortung.builder.strike.Strike() + dt = datetime.datetime.now(datetime.timezone.utc) + strike.set_timestamp(dt) + strike.set_id(42) + strike.set_x(8.5) + strike.set_y(50.2) + strike.set_altitude(1500.5) + strike.set_amplitude(45.3) + strike.set_lateral_error(300) + strike.set_station_count(12) + strike.set_stations([1, 2, 3, 4]) + + result = strike.build() + assert_that(result.id).is_equal_to(42) + assert_that(result.x).is_equal_to(8.5) + assert_that(result.y).is_equal_to(50.2) + assert_that(result.altitude).is_equal_to(1500.5) + assert_that(result.amplitude).is_equal_to(45.3) + assert_that(result.lateral_error).is_equal_to(300) + assert_that(result.station_count).is_equal_to(12) + assert_that(result.stations).is_equal_to([1, 2, 3, 4]) + + def test_build_with_default_id(self): + """Test building strike with default id value.""" + strike = blitzortung.builder.strike.Strike() + dt = datetime.datetime.now(datetime.timezone.utc) + strike.set_timestamp(dt).set_x(0).set_y(0) + + result = strike.build() + assert_that(result.id).is_equal_to(-1) # Default value + + def test_from_line_parsing_negative_coordinates(self): + """Test parsing strike with negative coordinates.""" + strike = blitzortung.builder.strike.Strike() + line = "2025-01-15T12:30:45.123456+00:00 pos;-48.5;-10.2;500.5 str;45.2 dev;250.0 sta;5;10;1,2,3,4,5" + + strike.from_line(line) + assert_that(strike.x_coord).is_equal_to(-10.2) + assert_that(strike.y_coord).is_equal_to(-48.5) diff --git a/tests/dataimport/test_dataimport_base.py b/tests/dataimport/test_dataimport_base.py new file mode 100644 index 0000000..062189f --- /dev/null +++ b/tests/dataimport/test_dataimport_base.py @@ -0,0 +1,255 @@ +# -*- coding: utf8 -*- + +""" + +Copyright 2014-2016 Andreas Würl + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +""" + +import os +import tempfile +from unittest.mock import Mock, patch, MagicMock + +from assertpy import assert_that # pylint: disable=import-error +import pytest # pylint: disable=import-error + +import blitzortung.dataimport.base + + +class TestFileTransport: + """Test suite for FileTransport class.""" + + def test_file_transport_is_transport_abstract(self): + """Test that FileTransport is a subclass of TransportAbstract.""" + assert_that( + issubclass( + blitzortung.dataimport.base.FileTransport, + blitzortung.dataimport.base.TransportAbstract, + ) + ).is_true() + + def test_read_lines_from_nonexistent_file(self): + """Test that read_lines returns nothing for nonexistent file.""" + transport = blitzortung.dataimport.base.FileTransport() + result = list(transport.read_lines("/nonexistent/path/to/file.txt")) + assert_that(result).is_empty() + + def test_read_lines_from_existing_file(self): + """Test that read_lines yields lines from existing file.""" + with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as tmp: + tmp.write("line 1\n") + tmp.write("line 2\n") + tmp.write("line 3\n") + tmp_path = tmp.name + + try: + transport = blitzortung.dataimport.base.FileTransport() + lines = list(transport.read_lines(tmp_path)) + assert_that(lines).is_length(3) + assert_that(lines[0]).is_equal_to("line 1\n") + assert_that(lines[1]).is_equal_to("line 2\n") + assert_that(lines[2]).is_equal_to("line 3\n") + finally: + os.unlink(tmp_path) + + def test_read_lines_is_generator(self): + """Test that read_lines returns a generator.""" + with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as tmp: + tmp.write("line 1\n") + tmp_path = tmp.name + + try: + transport = blitzortung.dataimport.base.FileTransport() + result = transport.read_lines(tmp_path) + # Check if it's a generator + assert_that(hasattr(result, "__iter__")).is_true() + assert_that(hasattr(result, "__next__")).is_true() + finally: + os.unlink(tmp_path) + + def test_read_lines_with_post_process(self): + """Test that post_process parameter is accepted.""" + with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as tmp: + tmp.write("line 1\n") + tmp_path = tmp.name + + try: + transport = blitzortung.dataimport.base.FileTransport() + result = list(transport.read_lines(tmp_path, post_process=lambda x: x)) + # FileTransport ignores post_process + assert_that(result).is_length(1) + finally: + os.unlink(tmp_path) + + def test_read_lines_empty_file(self): + """Test that read_lines handles empty file correctly.""" + with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as tmp: + tmp_path = tmp.name + + try: + transport = blitzortung.dataimport.base.FileTransport() + lines = list(transport.read_lines(tmp_path)) + assert_that(lines).is_empty() + finally: + os.unlink(tmp_path) + + +class TestBlitzortungDataPath: + """Test suite for BlitzortungDataPath class.""" + + def test_initialization_with_default_base_path(self): + """Test initialization with default base path.""" + path = blitzortung.dataimport.base.BlitzortungDataPath() + assert_that(path.data_path).contains("https://{host_name}.blitzortung.org") + + def test_initialization_with_custom_base_path(self): + """Test initialization with custom base path.""" + custom_path = "/custom/base" + path = blitzortung.dataimport.base.BlitzortungDataPath(custom_path) + assert_that(path.data_path).contains(custom_path) + + def test_default_host_name(self): + """Test default host name is 'data'.""" + assert_that( + blitzortung.dataimport.base.BlitzortungDataPath.default_host_name + ).is_equal_to("data") + + def test_default_region(self): + """Test default region is 1.""" + assert_that( + blitzortung.dataimport.base.BlitzortungDataPath.default_region + ).is_equal_to(1) + + def test_build_path_with_defaults(self): + """Test build_path with default parameters.""" + path = blitzortung.dataimport.base.BlitzortungDataPath() + result = path.build_path("subpath") + assert_that(result).contains("data.blitzortung.org") + assert_that(result).contains("subpath") + + def test_build_path_with_custom_host_name(self): + """Test build_path with custom host name.""" + path = blitzortung.dataimport.base.BlitzortungDataPath() + result = path.build_path("subpath", host_name="custom") + assert_that(result).contains("custom.blitzortung.org") + + def test_build_path_with_custom_region(self): + """Test build_path with custom region.""" + path = blitzortung.dataimport.base.BlitzortungDataPath() + result = path.build_path("subpath/{region}", region=5) + assert_that(result).contains("5") + + def test_build_path_formats_template(self): + """Test build_path correctly formats template strings.""" + custom_base = "https://example.com" + path = blitzortung.dataimport.base.BlitzortungDataPath(custom_base) + result = path.build_path("year/{region}/data") + assert_that(result).contains("example.com") + assert_that(result).contains("1") # default region + + +class TestBlitzortungDataPathGenerator: + """Test suite for BlitzortungDataPathGenerator class.""" + + def test_time_granularity(self): + """Test that time granularity is 10 minutes.""" + generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + assert_that(generator.time_granularity.total_seconds()).is_equal_to( + 600 + ) # 10 minutes + + def test_url_path_format(self): + """Test URL path format string.""" + generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + assert_that(generator.url_path_format).is_equal_to("%Y/%m/%d/%H/%M.log") + + def test_get_paths_single_interval(self): + """Test get_paths with single time interval.""" + import datetime + + generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + + start_time = datetime.datetime( + 2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc + ) + end_time = datetime.datetime( + 2025, 1, 15, 12, 10, 0, tzinfo=datetime.timezone.utc + ) + + paths = list(generator.get_paths(start_time, end_time)) + assert_that(paths).is_length(1) + assert_that(paths[0]).contains("2025/01/15/12/00.log") + + def test_get_paths_multiple_intervals(self): + """Test get_paths with multiple time intervals.""" + import datetime + + generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + + start_time = datetime.datetime( + 2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc + ) + end_time = datetime.datetime( + 2025, 1, 15, 12, 30, 0, tzinfo=datetime.timezone.utc + ) + + paths = list(generator.get_paths(start_time, end_time)) + # Should have 3 intervals: 12:00, 12:10, 12:20 + assert_that(paths).is_length(3) + + def test_get_paths_without_end_time(self): + """Test get_paths without end_time (yields only start_time).""" + import datetime + + generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + + start_time = datetime.datetime( + 2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc + ) + + paths = list(generator.get_paths(start_time)) + # Without end_time, should yield only the start time + assert_that(paths).is_length(1) + + def test_get_paths_formatting(self): + """Test that paths are correctly formatted with timestamp.""" + import datetime + + generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + + start_time = datetime.datetime( + 2025, 11, 14, 13, 45, 0, tzinfo=datetime.timezone.utc + ) + end_time = datetime.datetime( + 2025, 11, 14, 13, 55, 0, tzinfo=datetime.timezone.utc + ) + + paths = list(generator.get_paths(start_time, end_time)) + assert_that(paths[0]).is_equal_to("2025/11/14/13/45.log") + assert_that(paths[1]).is_equal_to("2025/11/14/13/55.log") + + def test_get_paths_is_generator(self): + """Test that get_paths returns a generator.""" + import datetime + + generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + + start_time = datetime.datetime( + 2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc + ) + + result = generator.get_paths(start_time) + assert_that(hasattr(result, "__iter__")).is_true() + assert_that(hasattr(result, "__next__")).is_true() diff --git a/tests/db/test_db_table.py b/tests/db/test_db_table.py new file mode 100644 index 0000000..e8a75ff --- /dev/null +++ b/tests/db/test_db_table.py @@ -0,0 +1,147 @@ +# -*- coding: utf8 -*- + +""" + +Copyright 2014-2016 Andreas Würl + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +""" + +import datetime + +from assertpy import assert_that # pylint: disable=import-error +import pytest # pylint: disable=import-error + +import blitzortung.db.table + + +class TestDatabaseTableBase: + """Test suite for db.table.Base class.""" + + def test_base_has_default_timezone(self): + """Test that Base has default timezone as UTC.""" + assert_that(blitzortung.db.table.Base.default_timezone).is_equal_to( + datetime.timezone.utc + ) + + def test_full_table_name_without_schema(self): + """Test full_table_name property without schema.""" + # We can't test this fully without a real DB connection, but we can test the concept + # by checking the method exists + assert_that(hasattr(blitzortung.db.table.Base, "full_table_name")).is_true() + + def test_strike_table_name(self): + """Test that Strike class has correct table name.""" + assert_that(blitzortung.db.table.Strike.table_name).is_equal_to("strikes") + + def test_timezone_property_exists(self): + """Test that Base has timezone property methods.""" + assert_that(hasattr(blitzortung.db.table.Base, "get_timezone")).is_true() + assert_that(hasattr(blitzortung.db.table.Base, "set_timezone")).is_true() + + def test_srid_property_exists(self): + """Test that Base has SRID property methods.""" + assert_that(hasattr(blitzortung.db.table.Base, "get_srid")).is_true() + assert_that(hasattr(blitzortung.db.table.Base, "set_srid")).is_true() + + def test_connection_check_method_exists(self): + """Test that Base has is_connected method.""" + assert_that(hasattr(blitzortung.db.table.Base, "is_connected")).is_true() + + def test_transaction_methods_exist(self): + """Test that Base has transaction methods.""" + assert_that(hasattr(blitzortung.db.table.Base, "commit")).is_true() + assert_that(hasattr(blitzortung.db.table.Base, "rollback")).is_true() + + def test_execute_methods_exist(self): + """Test that Base has various execute methods.""" + assert_that(hasattr(blitzortung.db.table.Base, "execute")).is_true() + assert_that(hasattr(blitzortung.db.table.Base, "execute_single")).is_true() + assert_that(hasattr(blitzortung.db.table.Base, "execute_many")).is_true() + + def test_timezone_conversion_methods_exist(self): + """Test that Base has timezone conversion methods.""" + assert_that(hasattr(blitzortung.db.table.Base, "fix_timezone")).is_true() + assert_that( + hasattr(blitzortung.db.table.Base, "from_bare_utc_to_timezone") + ).is_true() + assert_that( + hasattr(blitzortung.db.table.Base, "from_timezone_to_bare_utc") + ).is_true() + + +class TestStrikeTable: + """Test suite for db.table.Strike class.""" + + def test_strike_inherits_from_base(self): + """Test that Strike inherits from Base.""" + assert_that( + issubclass(blitzortung.db.table.Strike, blitzortung.db.table.Base) + ).is_true() + + def test_strike_table_name_is_strikes(self): + """Test that Strike table name is 'strikes'.""" + assert_that(blitzortung.db.table.Strike.table_name).is_equal_to("strikes") + + def test_strike_has_insert_method(self): + """Test that Strike has insert method.""" + assert_that(hasattr(blitzortung.db.table.Strike, "insert")).is_true() + assert_that(callable(blitzortung.db.table.Strike.insert)).is_true() + + def test_strike_has_select_method(self): + """Test that Strike has select method.""" + assert_that(hasattr(blitzortung.db.table.Strike, "select")).is_true() + assert_that(callable(blitzortung.db.table.Strike.select)).is_true() + + def test_strike_has_grid_methods(self): + """Test that Strike has grid query methods.""" + assert_that(hasattr(blitzortung.db.table.Strike, "select_grid")).is_true() + assert_that( + hasattr(blitzortung.db.table.Strike, "select_global_grid") + ).is_true() + + def test_strike_has_histogram_method(self): + """Test that Strike has histogram method.""" + assert_that(hasattr(blitzortung.db.table.Strike, "select_histogram")).is_true() + + def test_strike_has_get_latest_time_method(self): + """Test that Strike has get_latest_time method.""" + assert_that(hasattr(blitzortung.db.table.Strike, "get_latest_time")).is_true() + + def test_strike_initialization_requires_connection_pool(self): + """Test that Strike initialization signature includes db_connection_pool.""" + import inspect + + sig = inspect.signature(blitzortung.db.table.Strike.__init__) + param_names = list(sig.parameters.keys()) + # Should have self and db_connection_pool (plus other injected deps) + assert_that("db_connection_pool" in param_names).is_true() + + def test_strike_initialization_requires_query_builder(self): + """Test that Strike initialization includes query_builder.""" + import inspect + + sig = inspect.signature(blitzortung.db.table.Strike.__init__) + param_names = list(sig.parameters.keys()) + # Should include query builder parameter + assert_that(any("query_builder" in p for p in param_names)).is_true() + + def test_strike_initialization_requires_mapper(self): + """Test that Strike initialization includes strike_mapper.""" + import inspect + + sig = inspect.signature(blitzortung.db.table.Strike.__init__) + param_names = list(sig.parameters.keys()) + # Should include mapper parameter + assert_that(any("mapper" in p for p in param_names)).is_true() From 335019ed852b88fa962943496b7d852a5c975a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20W=C3=BCrl?= Date: Fri, 14 Nov 2025 15:27:58 +0100 Subject: [PATCH 2/5] fixed tests --- blitzortung/builder/strike.py | 2 +- tests/dataimport/test_dataimport_base.py | 34 ++++++---- tests/test_util.py | 84 ++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 14 deletions(-) diff --git a/blitzortung/builder/strike.py b/blitzortung/builder/strike.py index 993682a..2f9961b 100644 --- a/blitzortung/builder/strike.py +++ b/blitzortung/builder/strike.py @@ -32,7 +32,7 @@ class for building strike objects position_parser = re.compile(r'pos;([-0-9.]+);([-0-9.]+);([-0-9.]+)') amplitude_parser = re.compile(r'str;([0-9.]+)') deviation_parser = re.compile(r'dev;([0-9.]+)') - stations_parser = re.compile(r'sta;(\d+);(\d+);([^ ]+)') + stations_parser = re.compile(r'sta;(\d+);(\d+);([^ ]*)') def __init__(self): super().__init__() diff --git a/tests/dataimport/test_dataimport_base.py b/tests/dataimport/test_dataimport_base.py index 062189f..c7732c3 100644 --- a/tests/dataimport/test_dataimport_base.py +++ b/tests/dataimport/test_dataimport_base.py @@ -189,8 +189,9 @@ def test_get_paths_single_interval(self): ) paths = list(generator.get_paths(start_time, end_time)) - assert_that(paths).is_length(1) - assert_that(paths[0]).contains("2025/01/15/12/00.log") + assert_that(paths).is_length(2) + assert_that(paths[0]).is_equal_to("2025/01/15/12/00.log") + assert_that(paths[1]).is_equal_to("2025/01/15/12/10.log") def test_get_paths_multiple_intervals(self): """Test get_paths with multiple time intervals.""" @@ -206,25 +207,30 @@ def test_get_paths_multiple_intervals(self): ) paths = list(generator.get_paths(start_time, end_time)) - # Should have 3 intervals: 12:00, 12:10, 12:20 - assert_that(paths).is_length(3) + # Should have 4 intervals: 12:00, 12:10, 12:20, 12:30 + assert_that(paths).is_length(4) + assert_that(paths[0]).is_equal_to("2025/01/15/12/00.log") + assert_that(paths[1]).is_equal_to("2025/01/15/12/10.log") + assert_that(paths[2]).is_equal_to("2025/01/15/12/20.log") + assert_that(paths[3]).is_equal_to("2025/01/15/12/30.log") def test_get_paths_without_end_time(self): - """Test get_paths without end_time (yields only start_time).""" + """Test get_paths without end_time defaults to current time.""" import datetime generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() - start_time = datetime.datetime( - 2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc - ) + # Use current time for start to avoid generating thousands of intervals + start_time = datetime.datetime.now(datetime.timezone.utc) paths = list(generator.get_paths(start_time)) - # Without end_time, should yield only the start time - assert_that(paths).is_length(1) + # Should yield at least the start time interval + assert_that(paths).is_not_empty() + # First path should be for the rounded start time + assert_that(paths[0]).matches(r'\d{4}/\d{2}/\d{2}/\d{2}/\d{2}\.log') def test_get_paths_formatting(self): - """Test that paths are correctly formatted with timestamp.""" + """Test that paths are correctly formatted with timestamp and rounded to 10-minute intervals.""" import datetime generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() @@ -237,8 +243,10 @@ def test_get_paths_formatting(self): ) paths = list(generator.get_paths(start_time, end_time)) - assert_that(paths[0]).is_equal_to("2025/11/14/13/45.log") - assert_that(paths[1]).is_equal_to("2025/11/14/13/55.log") + # Times are rounded down to 10-minute intervals + assert_that(paths).is_length(2) + assert_that(paths[0]).is_equal_to("2025/11/14/13/40.log") + assert_that(paths[1]).is_equal_to("2025/11/14/13/50.log") def test_get_paths_is_generator(self): """Test that get_paths returns a generator.""" diff --git a/tests/test_util.py b/tests/test_util.py index e5861a4..a52d0d4 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -131,3 +131,87 @@ def test_limit_value_below_rage(self): def test_limit_value_above_rage(self): assert blitzortung.util.force_range(10,21,20) == 20 + + +class TestTimer: + """Test Timer class for time measurements.""" + + def test_timer_initialization(self): + """Test that Timer initializes with start and lap times.""" + timer = blitzortung.util.Timer() + + assert_that(timer.start_time).is_not_none() + assert_that(timer.lap_time).is_equal_to(timer.start_time) + + def test_timer_read(self): + """Test reading elapsed time from timer.""" + import time + timer = blitzortung.util.Timer() + time.sleep(0.01) + + elapsed = timer.read() + + assert_that(elapsed).is_greater_than_or_equal_to(0.01) + assert_that(elapsed).is_less_than(1.0) + + def test_timer_lap(self): + """Test lap functionality returns lap time and resets.""" + import time + timer = blitzortung.util.Timer() + time.sleep(0.01) + + lap1 = timer.lap() + assert_that(lap1).is_greater_than_or_equal_to(0.01) + assert_that(lap1).is_less_than(1.0) + + time.sleep(0.01) + lap2 = timer.lap() + assert_that(lap2).is_greater_than_or_equal_to(0.01) + assert_that(lap2).is_less_than(1.0) + + +class TestTotalSeconds: + """Test total_seconds function with different time types.""" + + def test_total_seconds_with_datetime(self): + """Test total_seconds with datetime object.""" + time_value = datetime.datetime(2013, 8, 20, 12, 30, 45) + + result = blitzortung.util.total_seconds(time_value) + + expected = 12 * 3600 + 30 * 60 + 45 + assert_that(result).is_equal_to(expected) + + def test_total_seconds_with_timestamp(self): + """Test total_seconds with Timestamp object.""" + time_value = Timestamp(datetime.datetime(2013, 8, 20, 5, 15, 30), 123) + + result = blitzortung.util.total_seconds(time_value) + + expected = 5 * 3600 + 15 * 60 + 30 + assert_that(result).is_equal_to(expected) + + def test_total_seconds_with_timedelta(self): + """Test total_seconds with timedelta object.""" + time_value = datetime.timedelta(hours=2, minutes=30, seconds=15) + + result = blitzortung.util.total_seconds(time_value) + + expected = 2 * 3600 + 30 * 60 + 15 + assert_that(result).is_equal_to(expected) + + def test_total_seconds_with_timedelta_including_days(self): + """Test total_seconds with timedelta including days.""" + time_value = datetime.timedelta(days=2, hours=3, minutes=15, seconds=30) + + result = blitzortung.util.total_seconds(time_value) + + expected = 2 * 24 * 3600 + 3 * 3600 + 15 * 60 + 30 + assert_that(result).is_equal_to(expected) + + def test_total_seconds_with_invalid_type(self): + """Test total_seconds raises ValueError with invalid type.""" + import pytest + + with pytest.raises(ValueError, match="unhandled type"): + blitzortung.util.total_seconds("invalid") From 9e42f78e9b0eda44505447faaf7a3eb9f25b24ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20W=C3=BCrl?= Date: Fri, 14 Nov 2025 15:35:00 +0100 Subject: [PATCH 3/5] wip --- tests/dataimport/test_dataimport_base.py | 91 +++++++----------------- tests/dataimport/test_dataimport_init.py | 30 ++++++++ tests/db/test_db_init.py | 39 ++++++++++ tests/service/test_service_init.py | 41 +++++++++++ tests/test_util.py | 80 ++++++--------------- 5 files changed, 159 insertions(+), 122 deletions(-) create mode 100644 tests/dataimport/test_dataimport_init.py create mode 100644 tests/db/test_db_init.py create mode 100644 tests/service/test_service_init.py diff --git a/tests/dataimport/test_dataimport_base.py b/tests/dataimport/test_dataimport_base.py index c7732c3..27e541f 100644 --- a/tests/dataimport/test_dataimport_base.py +++ b/tests/dataimport/test_dataimport_base.py @@ -161,103 +161,66 @@ def test_build_path_formats_template(self): class TestBlitzortungDataPathGenerator: - """Test suite for BlitzortungDataPathGenerator class.""" def test_time_granularity(self): - """Test that time granularity is 10 minutes.""" generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() - assert_that(generator.time_granularity.total_seconds()).is_equal_to( - 600 - ) # 10 minutes + assert_that(generator.time_granularity.total_seconds()).is_equal_to(600) def test_url_path_format(self): - """Test URL path format string.""" generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() assert_that(generator.url_path_format).is_equal_to("%Y/%m/%d/%H/%M.log") def test_get_paths_single_interval(self): - """Test get_paths with single time interval.""" import datetime - generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + start = datetime.datetime(2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc) + end = datetime.datetime(2025, 1, 15, 12, 10, 0, tzinfo=datetime.timezone.utc) - start_time = datetime.datetime( - 2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc - ) - end_time = datetime.datetime( - 2025, 1, 15, 12, 10, 0, tzinfo=datetime.timezone.utc - ) + paths = list(generator.get_paths(start, end)) - paths = list(generator.get_paths(start_time, end_time)) - assert_that(paths).is_length(2) - assert_that(paths[0]).is_equal_to("2025/01/15/12/00.log") - assert_that(paths[1]).is_equal_to("2025/01/15/12/10.log") + assert_that(paths).is_equal_to(["2025/01/15/12/00.log", "2025/01/15/12/10.log"]) def test_get_paths_multiple_intervals(self): - """Test get_paths with multiple time intervals.""" import datetime - generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + start = datetime.datetime(2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc) + end = datetime.datetime(2025, 1, 15, 12, 30, 0, tzinfo=datetime.timezone.utc) - start_time = datetime.datetime( - 2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc - ) - end_time = datetime.datetime( - 2025, 1, 15, 12, 30, 0, tzinfo=datetime.timezone.utc - ) - - paths = list(generator.get_paths(start_time, end_time)) - # Should have 4 intervals: 12:00, 12:10, 12:20, 12:30 - assert_that(paths).is_length(4) - assert_that(paths[0]).is_equal_to("2025/01/15/12/00.log") - assert_that(paths[1]).is_equal_to("2025/01/15/12/10.log") - assert_that(paths[2]).is_equal_to("2025/01/15/12/20.log") - assert_that(paths[3]).is_equal_to("2025/01/15/12/30.log") + paths = list(generator.get_paths(start, end)) + + assert_that(paths).is_equal_to([ + "2025/01/15/12/00.log", + "2025/01/15/12/10.log", + "2025/01/15/12/20.log", + "2025/01/15/12/30.log" + ]) def test_get_paths_without_end_time(self): - """Test get_paths without end_time defaults to current time.""" import datetime - generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + start = datetime.datetime.now(datetime.timezone.utc) - # Use current time for start to avoid generating thousands of intervals - start_time = datetime.datetime.now(datetime.timezone.utc) + paths = list(generator.get_paths(start)) - paths = list(generator.get_paths(start_time)) - # Should yield at least the start time interval assert_that(paths).is_not_empty() - # First path should be for the rounded start time assert_that(paths[0]).matches(r'\d{4}/\d{2}/\d{2}/\d{2}/\d{2}\.log') - def test_get_paths_formatting(self): - """Test that paths are correctly formatted with timestamp and rounded to 10-minute intervals.""" + def test_get_paths_rounds_to_intervals(self): import datetime - generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + start = datetime.datetime(2025, 11, 14, 13, 45, 0, tzinfo=datetime.timezone.utc) + end = datetime.datetime(2025, 11, 14, 13, 55, 0, tzinfo=datetime.timezone.utc) - start_time = datetime.datetime( - 2025, 11, 14, 13, 45, 0, tzinfo=datetime.timezone.utc - ) - end_time = datetime.datetime( - 2025, 11, 14, 13, 55, 0, tzinfo=datetime.timezone.utc - ) - - paths = list(generator.get_paths(start_time, end_time)) - # Times are rounded down to 10-minute intervals - assert_that(paths).is_length(2) - assert_that(paths[0]).is_equal_to("2025/11/14/13/40.log") - assert_that(paths[1]).is_equal_to("2025/11/14/13/50.log") - - def test_get_paths_is_generator(self): - """Test that get_paths returns a generator.""" - import datetime + paths = list(generator.get_paths(start, end)) + assert_that(paths).is_equal_to(["2025/11/14/13/40.log", "2025/11/14/13/50.log"]) + + def test_get_paths_returns_generator(self): + import datetime generator = blitzortung.dataimport.base.BlitzortungDataPathGenerator() + start = datetime.datetime(2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc) - start_time = datetime.datetime( - 2025, 1, 15, 12, 0, 0, tzinfo=datetime.timezone.utc - ) + result = generator.get_paths(start) - result = generator.get_paths(start_time) assert_that(hasattr(result, "__iter__")).is_true() assert_that(hasattr(result, "__next__")).is_true() diff --git a/tests/dataimport/test_dataimport_init.py b/tests/dataimport/test_dataimport_init.py new file mode 100644 index 0000000..0d88287 --- /dev/null +++ b/tests/dataimport/test_dataimport_init.py @@ -0,0 +1,30 @@ +# -*- coding: utf8 -*- + +""" + + Copyright 2014-2016 Andreas Würl + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +""" + +from assertpy import assert_that + +import blitzortung.dataimport +import blitzortung.dataimport.strike + + +class TestDataimportFactoryFunctions: + + def test_strikes_factory(self): + assert_that(blitzortung.dataimport.strikes()).is_instance_of(blitzortung.dataimport.strike.StrikesBlitzortungDataProvider) diff --git a/tests/db/test_db_init.py b/tests/db/test_db_init.py new file mode 100644 index 0000000..1860329 --- /dev/null +++ b/tests/db/test_db_init.py @@ -0,0 +1,39 @@ +# -*- coding: utf8 -*- + +""" + + Copyright 2025 Andreas Würl + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +""" + +from assertpy import assert_that +from mock import Mock + +import blitzortung.db +import blitzortung.db.table + + +class TestDbFactoryFunctions: + + def test_strike_factory(self): + assert_that(blitzortung.db.strike()).is_instance_of(blitzortung.db.table.Strike) + + +class TestDbModule: + + def test_cleanup_closes_connection_pool(self): + connection_pool = Mock() + blitzortung.db.DbModule.cleanup(connection_pool) + connection_pool.closeall.assert_called_once() diff --git a/tests/service/test_service_init.py b/tests/service/test_service_init.py new file mode 100644 index 0000000..c4f7749 --- /dev/null +++ b/tests/service/test_service_init.py @@ -0,0 +1,41 @@ +# -*- coding: utf8 -*- + +""" + + Copyright 2025 Andreas Würl + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +""" + +from assertpy import assert_that + +import blitzortung.service +import blitzortung.service.strike +import blitzortung.service.strike_grid +import blitzortung.service.histogram + + +class TestServiceFactoryFunctions: + + def test_strike_query_factory(self): + assert_that(blitzortung.service.strike_query()).is_instance_of(blitzortung.service.strike.StrikeQuery) + + def test_strike_grid_query_factory(self): + assert_that(blitzortung.service.strike_grid_query()).is_instance_of(blitzortung.service.strike_grid.StrikeGridQuery) + + def test_global_strike_grid_query_factory(self): + assert_that(blitzortung.service.global_strike_grid_query()).is_instance_of(blitzortung.service.strike_grid.GlobalStrikeGridQuery) + + def test_histogram_query_factory(self): + assert_that(blitzortung.service.histogram_query()).is_instance_of(blitzortung.service.histogram.HistogramQuery) diff --git a/tests/test_util.py b/tests/test_util.py index a52d0d4..299c958 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -19,7 +19,9 @@ """ import datetime +import time +import pytest from assertpy import assert_that import blitzortung.util @@ -134,84 +136,46 @@ def test_limit_value_above_rage(self): class TestTimer: - """Test Timer class for time measurements.""" - def test_timer_initialization(self): - """Test that Timer initializes with start and lap times.""" + def test_initialization(self): timer = blitzortung.util.Timer() - assert_that(timer.start_time).is_not_none() assert_that(timer.lap_time).is_equal_to(timer.start_time) - def test_timer_read(self): - """Test reading elapsed time from timer.""" - import time + def test_read(self): timer = blitzortung.util.Timer() time.sleep(0.01) + assert_that(timer.read()).is_between(0.01, 1.0) - elapsed = timer.read() - - assert_that(elapsed).is_greater_than_or_equal_to(0.01) - assert_that(elapsed).is_less_than(1.0) - - def test_timer_lap(self): - """Test lap functionality returns lap time and resets.""" - import time + def test_lap(self): timer = blitzortung.util.Timer() time.sleep(0.01) - lap1 = timer.lap() - assert_that(lap1).is_greater_than_or_equal_to(0.01) - assert_that(lap1).is_less_than(1.0) - time.sleep(0.01) lap2 = timer.lap() - assert_that(lap2).is_greater_than_or_equal_to(0.01) - assert_that(lap2).is_less_than(1.0) - - -class TestTotalSeconds: - """Test total_seconds function with different time types.""" - def test_total_seconds_with_datetime(self): - """Test total_seconds with datetime object.""" - time_value = datetime.datetime(2013, 8, 20, 12, 30, 45) + assert_that(lap1).is_between(0.01, 1.0) + assert_that(lap2).is_between(0.01, 1.0) - result = blitzortung.util.total_seconds(time_value) - expected = 12 * 3600 + 30 * 60 + 45 - assert_that(result).is_equal_to(expected) - - def test_total_seconds_with_timestamp(self): - """Test total_seconds with Timestamp object.""" - time_value = Timestamp(datetime.datetime(2013, 8, 20, 5, 15, 30), 123) - - result = blitzortung.util.total_seconds(time_value) - - expected = 5 * 3600 + 15 * 60 + 30 - assert_that(result).is_equal_to(expected) - - def test_total_seconds_with_timedelta(self): - """Test total_seconds with timedelta object.""" - time_value = datetime.timedelta(hours=2, minutes=30, seconds=15) - - result = blitzortung.util.total_seconds(time_value) - - expected = 2 * 3600 + 30 * 60 + 15 - assert_that(result).is_equal_to(expected) +class TestTotalSeconds: - def test_total_seconds_with_timedelta_including_days(self): - """Test total_seconds with timedelta including days.""" - time_value = datetime.timedelta(days=2, hours=3, minutes=15, seconds=30) + def test_with_datetime(self): + result = blitzortung.util.total_seconds(datetime.datetime(2013, 8, 20, 12, 30, 45)) + assert_that(result).is_equal_to(12 * 3600 + 30 * 60 + 45) - result = blitzortung.util.total_seconds(time_value) + def test_with_timestamp(self): + result = blitzortung.util.total_seconds(Timestamp(datetime.datetime(2013, 8, 20, 5, 15, 30), 123)) + assert_that(result).is_equal_to(5 * 3600 + 15 * 60 + 30) - expected = 2 * 24 * 3600 + 3 * 3600 + 15 * 60 + 30 - assert_that(result).is_equal_to(expected) + def test_with_timedelta(self): + result = blitzortung.util.total_seconds(datetime.timedelta(hours=2, minutes=30, seconds=15)) + assert_that(result).is_equal_to(2 * 3600 + 30 * 60 + 15) - def test_total_seconds_with_invalid_type(self): - """Test total_seconds raises ValueError with invalid type.""" - import pytest + def test_with_timedelta_and_days(self): + result = blitzortung.util.total_seconds(datetime.timedelta(days=2, hours=3, minutes=15, seconds=30)) + assert_that(result).is_equal_to(2 * 24 * 3600 + 3 * 3600 + 15 * 60 + 30) + def test_invalid_type_raises_error(self): with pytest.raises(ValueError, match="unhandled type"): blitzortung.util.total_seconds("invalid") From 26b9cb32f9f4b85f5fb0f3c48703148854f52436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20W=C3=BCrl?= Date: Fri, 14 Nov 2025 15:48:15 +0100 Subject: [PATCH 4/5] clean up tests --- blitzortung/builder/strike.py | 2 +- pylint.rc | 4 +- tests/dataimport/test_dataimport_base.py | 20 +++--- tests/dataimport/test_dataimport_init.py | 2 +- tests/test_convert.py | 86 +++++------------------- tests/test_util.py | 2 +- 6 files changed, 32 insertions(+), 84 deletions(-) diff --git a/blitzortung/builder/strike.py b/blitzortung/builder/strike.py index 2f9961b..60b965d 100644 --- a/blitzortung/builder/strike.py +++ b/blitzortung/builder/strike.py @@ -2,7 +2,7 @@ """ - Copyright 2014-2022 Andreas Würl + Copyright 2014-2025 Andreas Würl Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/pylint.rc b/pylint.rc index e411dd5..58bdc38 100644 --- a/pylint.rc +++ b/pylint.rc @@ -12,7 +12,7 @@ profile=no # Add files or directories to the blacklist. They should be base names, not # paths. -ignore=CVS +ignore=CVS,tests # Pickle collected data for later comparisons. persistent=yes @@ -123,7 +123,7 @@ bad-names=foo,bar,baz,toto,tutu,tata # Regular expression which should only match functions or classes name which do # not require a docstring -no-docstring-rgx=__.*__ +no-docstring-rgx=(__.*__|test_.*|Test.*) [FORMAT] diff --git a/tests/dataimport/test_dataimport_base.py b/tests/dataimport/test_dataimport_base.py index 27e541f..527d507 100644 --- a/tests/dataimport/test_dataimport_base.py +++ b/tests/dataimport/test_dataimport_base.py @@ -2,19 +2,19 @@ """ -Copyright 2014-2016 Andreas Würl + Copyright 2025 Andreas Würl -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. """ diff --git a/tests/dataimport/test_dataimport_init.py b/tests/dataimport/test_dataimport_init.py index 0d88287..afe4e18 100644 --- a/tests/dataimport/test_dataimport_init.py +++ b/tests/dataimport/test_dataimport_init.py @@ -2,7 +2,7 @@ """ - Copyright 2014-2016 Andreas Würl + Copyright 2025 Andreas Würl Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/tests/test_convert.py b/tests/test_convert.py index 655d713..68c2509 100644 --- a/tests/test_convert.py +++ b/tests/test_convert.py @@ -2,92 +2,40 @@ """ -Copyright 2014-2016 Andreas Würl + Copyright 2025 Andreas Würl -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. """ -from assertpy import assert_that # pylint: disable=import-error +from assertpy import assert_that import blitzortung.convert class TestValueToString: - """Test suite for value_to_string conversion utility.""" - def test_float_formatting_with_four_decimals(self): - """Test float values are formatted with 4 decimal places.""" + def test_float_with_four_decimals(self): assert_that(blitzortung.convert.value_to_string(3.14159)).is_equal_to("3.1416") def test_float_zero(self): - """Test float zero is formatted correctly.""" assert_that(blitzortung.convert.value_to_string(0.0)).is_equal_to("0.0000") - def test_integer_converted_to_string(self): - """Test integer values are converted to string.""" - assert_that(blitzortung.convert.value_to_string(42)).is_equal_to("42") - - def test_string_passed_through(self): - """Test string values are passed through unchanged.""" - assert_that( - blitzortung.convert.value_to_string("already a string") - ).is_equal_to("already a string") - def test_negative_float(self): - """Test negative float formatting.""" - assert_that(blitzortung.convert.value_to_string(-2.71828)).is_equal_to( - "-2.7183" - ) - - def test_very_small_float(self): - """Test very small float is formatted correctly.""" - assert_that(blitzortung.convert.value_to_string(0.0001)).is_equal_to("0.0001") - - def test_very_large_float(self): - """Test very large float is formatted correctly.""" - assert_that(blitzortung.convert.value_to_string(123456.789)).is_equal_to( - "123456.7890" - ) - - def test_scientific_notation_float(self): - """Test float with scientific notation.""" - result = blitzortung.convert.value_to_string(1.23e-5) - assert_that(result).is_equal_to("0.0000") + assert_that(blitzortung.convert.value_to_string(-2.71828)).is_equal_to("-2.7183") - def test_none_value(self): - """Test None value is converted to string.""" - assert_that(blitzortung.convert.value_to_string(None)).is_equal_to("None") + def test_large_float(self): + assert_that(blitzortung.convert.value_to_string(123456.789)).is_equal_to("123456.7890") - def test_bool_true(self): - """Test boolean True is converted to string.""" - assert_that(blitzortung.convert.value_to_string(True)).is_equal_to("True") - - def test_bool_false(self): - """Test boolean False is converted to string.""" - assert_that(blitzortung.convert.value_to_string(False)).is_equal_to("False") - - def test_float_infinity(self): - """Test infinity float formatting.""" - result = blitzortung.convert.value_to_string(float("inf")) - assert_that(result).is_equal_to("inf") - - def test_float_negative_infinity(self): - """Test negative infinity float formatting.""" - result = blitzortung.convert.value_to_string(float("-inf")) - assert_that(result).is_equal_to("-inf") - - def test_float_nan(self): - """Test NaN float formatting.""" - result = blitzortung.convert.value_to_string(float("nan")) - assert_that(result).is_equal_to("nan") + def test_non_float(self): + assert_that(blitzortung.convert.value_to_string(42)).is_equal_to("42") diff --git a/tests/test_util.py b/tests/test_util.py index 299c958..ac9b0b9 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -2,7 +2,7 @@ """ - Copyright 2014-2016 Andreas Würl + Copyright 2013-2025 Andreas Würl Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 6d75029b87784a07d8f4758bf8cc2c2b48782881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20W=C3=BCrl?= Date: Fri, 14 Nov 2025 15:59:43 +0100 Subject: [PATCH 5/5] fix --- tests/dataimport/test_dataimport_init.py | 30 ------------------------ tests/db/test_db_init.py | 8 ------- 2 files changed, 38 deletions(-) delete mode 100644 tests/dataimport/test_dataimport_init.py diff --git a/tests/dataimport/test_dataimport_init.py b/tests/dataimport/test_dataimport_init.py deleted file mode 100644 index afe4e18..0000000 --- a/tests/dataimport/test_dataimport_init.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf8 -*- - -""" - - Copyright 2025 Andreas Würl - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -""" - -from assertpy import assert_that - -import blitzortung.dataimport -import blitzortung.dataimport.strike - - -class TestDataimportFactoryFunctions: - - def test_strikes_factory(self): - assert_that(blitzortung.dataimport.strikes()).is_instance_of(blitzortung.dataimport.strike.StrikesBlitzortungDataProvider) diff --git a/tests/db/test_db_init.py b/tests/db/test_db_init.py index 1860329..8c9ba73 100644 --- a/tests/db/test_db_init.py +++ b/tests/db/test_db_init.py @@ -18,17 +18,9 @@ """ -from assertpy import assert_that from mock import Mock import blitzortung.db -import blitzortung.db.table - - -class TestDbFactoryFunctions: - - def test_strike_factory(self): - assert_that(blitzortung.db.strike()).is_instance_of(blitzortung.db.table.Strike) class TestDbModule: