Repository: conan-io/conan

Issue:
[bug] Duplicate Version comparison unittests
### Environment details

I've noticed there is a large overlap between `/conans/test/unittests/model/version_test.py` and `conans/test/unittests/model/version/test_version_comparison.py`.

I can make the changes and create a pull request?

### Steps to reproduce

_No response_

### Logs

_No response_


Discussion:
Hi @jputcu thanks a lot for your proposal, we would love it if you did this yes!

Only 1 note: make sure to keep test cases that check for regressions, or make it explicit in what test they end up from, they are usually marked by a link to a gh issue or a message explaining the reason for the tests :)

Let us know if we can help you in any way!

Resolving patch:
diff --git a/conans/model/version.py b/conans/model/version.py
--- a/conans/model/version.py
+++ b/conans/model/version.py
@@ -70,6 +70,7 @@ def __init__(self, value):
         else:
             value = items[0]
             self._pre = None
+
         items = value.split(".")
         items = [_VersionItem(item) for item in items]
         self._items = tuple(items)
@@ -99,8 +100,7 @@ def bump(self, index):
         items.extend([0] * (len(items) - index - 1))
         v = ".".join(str(i) for i in items)
         # prerelease and build are dropped while bumping digits
-        result = Version(v)
-        return result
+        return Version(v)
 
     def upper_bound(self, index):
         items = list(self._items[:index])
@@ -111,8 +111,7 @@ def upper_bound(self, index):
         items.extend([0] * (len(items) - index - 1))
         v = ".".join(str(i) for i in items)
         v += "-"  # Exclude prereleases
-        result = Version(v)
-        return result
+        return Version(v)
 
     @property
     def pre(self):


Test patch:
diff --git a/conans/test/unittests/model/version/test_version_bump.py b/conans/test/unittests/model/version/test_version_bump.py
--- a/conans/test/unittests/model/version/test_version_bump.py
+++ b/conans/test/unittests/model/version/test_version_bump.py
@@ -1,6 +1,6 @@
 import pytest
 
-from conans.model.recipe_ref import Version
+from conans.model.version import Version
 
 values = [
     ['1.0.0',       0, "2.0.0"],
diff --git a/conans/test/unittests/model/version/test_version_comparison.py b/conans/test/unittests/model/version/test_version_comparison.py
--- a/conans/test/unittests/model/version/test_version_comparison.py
+++ b/conans/test/unittests/model/version/test_version_comparison.py
@@ -1,6 +1,6 @@
 import pytest
 
-from conans.model.recipe_ref import Version
+from conans.model.version import Version
 
 v = [("1", "2"),
      ("1.0", "1.1"),
@@ -13,6 +13,12 @@
      ("1.0", "2"),
      ("1.2", "1.3.1"),
      ("1.0.2", "1.1"),
+     ("1.2.3", "1.11"),
+     ("1.2", "1.2.3"),
+     ("1.2.2.2", "1.2.3"),
+     ("1.2.3", "1.2.3.2"),
+     ("4", "4.0.1"),
+     ("4", "4.0.0.1"),
      # Now with letters
      ("1.1.a", "1.1.b"),
      ("1.1.1.abc", "1.1.1.abz"),
@@ -38,8 +44,18 @@
      ("1.1-alpha.1", "1.1"),
      ("1.1", "1.2-alpha1"),
      ("1.1-alpha.1", "1.1.0"),  # pre to the generic 1.1 is earlier than 1.1.0
-     ("1.0.0-", "1.0.0-alpha1")
-]
+     ("1.0.0-", "1.0.0-alpha1"),
+     ("1.2-rc1", "1.2.0"),
+     ("1.1.9", "1.2-rc1"),
+     # development versions
+     ("1.2.1-dev", "1.2.1"),
+     ("1.2.1-dev", "1.2.2"),
+     ("1.2.1-dev", "1.3"),
+     ("1.2.1-dev", "1.3-alpha"),
+     ("1.2.0", "1.2.1-dev"),
+     ("1.2", "1.2.1-dev"),
+     ("1.2-alpha", "1.2.1-dev"),
+     ]
 
 
 @pytest.mark.parametrize("v1, v2", v)
@@ -53,6 +69,18 @@ def test_comparison(v1, v2):
     assert v2 >= v1
 
 
+def test_build_metadata_is_not_equal():
+    # https://github.com/conan-io/conan/issues/5900
+    # Shouldn't be an "official" order for build metadata, but as they cannot be equal
+    # the order is alphabetic
+    assert Version("4.0.0+abc") != Version("4.0.0+xyz")
+    assert Version("4.0.0+xyz") != Version("4.0.0+abc")
+
+
+def test_comparison_with_none():
+    assert Version("1.2.3") > None
+
+
 def test_comparison_with_integer():
     v1 = Version("13.0")
     # Issue: https://github.com/conan-io/conan/issues/12907
@@ -79,6 +107,7 @@ def test_comparison_with_integer():
      ("1+b1", "1.0+b1.0"),
      ("1+b1", "1.0.0+b1"),
      ("1.0+b1", "1.0.0+b1"),
+     ("1.2.3", "1.2.3"),
      ]
 
 
@@ -88,6 +117,10 @@ def test_equality(v1, v2):
     v2 = Version(v2)
     assert v1 == v2
     assert not v1 != v2
+    assert not v1 < v2
+    assert not v2 < v1
+    assert v1 <= v2
+    assert v2 <= v1
 
 
 def test_elem_comparison():
diff --git a/conans/test/unittests/model/version/test_version_parse.py b/conans/test/unittests/model/version/test_version_parse.py
new file mode 100644
--- /dev/null
+++ b/conans/test/unittests/model/version/test_version_parse.py
@@ -0,0 +1,38 @@
+import pytest
+
+from conans.model.version import Version
+
+v = [("1.2.3",
+      (1, 2, 3), None, None),
+     ("1.2.3",
+      ('1', '2', '3'), None, None),
+     ("master+build2",
+      'master', None, "build2"),
+     ("1.2.3-alpha1+build2",
+      (1, 2, 3), "alpha1", "build2"),
+     ("1.2.3+build2",
+      (1, 2, 3), None, "build2"),
+     ("1.2.3b.4-pre.1.2b+build.1.1b",
+      (1, 2, "3b", 4), "pre.1.2b", "build.1.1b"),
+     ("0.2.3+b178",
+      (0, 2, 3), None, "b178"),
+     ("1.2.3.4.5",
+      (1, 2, 3, 4, 5), None, None),
+     (9,
+      9, None, None),
+     (1.2,
+      (1, 2), None, None),
+     ("",
+      '', None, None),
+     ("+build2",
+      '', None, "build2"),
+     ]
+
+
+@pytest.mark.parametrize("v_str, main, build, pre", v)
+def test_parse(v_str, main, build, pre):
+    v1 = Version(v_str)
+    assert v1.main == main if type(main) is tuple else tuple([main])
+    assert v1.pre == build
+    assert v1.build == pre
+    assert str(v1) == str(v_str)
diff --git a/conans/test/unittests/model/version/test_version_range.py b/conans/test/unittests/model/version/test_version_range.py
--- a/conans/test/unittests/model/version/test_version_range.py
+++ b/conans/test/unittests/model/version/test_version_range.py
@@ -1,7 +1,7 @@
 import pytest
 
 from conans.errors import ConanException
-from conans.model.recipe_ref import Version
+from conans.model.version import Version
 from conans.model.version_range import VersionRange
 
 values = [
diff --git a/conans/test/unittests/model/version_test.py b/conans/test/unittests/model/version_test.py
deleted file mode 100644
--- a/conans/test/unittests/model/version_test.py
+++ /dev/null
@@ -1,108 +0,0 @@
-import unittest
-
-from conans.model.info import _VersionRepr
-from conans.model.version import Version
-
-
-class VersionTest(unittest.TestCase):
-
-    def test_simple(self):
-        v1 = Version("1.2.3")
-        self.assertTrue(v1 == "1.2.3")
-        self.assertTrue(v1 > "1.1")
-        self.assertTrue(v1 > None)
-        self.assertTrue(v1 < "1.11")
-        self.assertTrue(v1 > "1.2")
-        self.assertTrue(v1 > "1.2.2.2")
-        self.assertTrue(v1 < "1.2.3.2")
-        self.assertEqual(v1.major, "1")  # 1.X.Y
-        self.assertEqual(v1.minor, "2")  # 1.2.Y
-        self.assertEqual(v1.patch, "3")
-        self.assertEqual(v1.pre, None)
-        self.assertEqual(v1.build, None)
-
-        v1 = Version("1.2-rc1")
-        self.assertTrue(v1 < "1.2.0")
-        self.assertFalse(v1 < "1.1.9")
-
-        self.assertTrue(Version("1.2.1-dev") < Version("1.2.1"))
-        self.assertTrue(Version("1.2.1-dev") < Version("1.2.2"))
-        self.assertTrue(Version("1.2.1-dev") < Version("1.3"))
-        self.assertTrue(Version("1.2.1-dev") < Version("1.3-alpha"))
-        self.assertTrue(Version("1.2.1-dev") > Version("1.2.0"))
-        self.assertTrue(Version("1.2.1-dev") > Version("1.2"))
-        self.assertTrue(Version("1.2.1-dev") > Version("1.2-alpha"))
-
-        self.assertFalse(Version("4") < Version("4.0.0"))
-        self.assertFalse(Version("4") > Version("4.0.0"))
-        self.assertFalse(Version("4") != Version("4.0.0"))
-        self.assertTrue(Version("4") == Version("4.0.0"))
-        self.assertTrue(Version("4") <= Version("4.0.0"))
-        self.assertTrue(Version("4") >= Version("4.0.0"))
-        self.assertTrue(Version("4.0") == Version("4.0.0"))
-
-        self.assertTrue(Version("4.0.0") == Version("4.0.0"))
-        self.assertTrue(Version("4.0.1") != "4")
-        self.assertFalse(Version("4.0.0.1") == "4")
-        self.assertTrue(Version("4.0.0.1") >= "4")
-
-    def test_build_metadata_is_not_equal(self):
-        # https://github.com/conan-io/conan/issues/5900
-        self.assertNotEqual(Version("4.0.0+abc"), Version("4.0.0+xyz"))
-        # Shouldn't be an "official" order for build metadata, but as they cannot be equal
-        # the order is alphabetic
-        self.assertTrue(Version("4.0.0+abc") != Version("4.0.0+xyz"))
-        self.assertTrue(Version("4.0.0+xyz") != Version("4.0.0+abc"))
-
-    def test_text(self):
-        from conans.model.recipe_ref import Version
-        v1 = Version("master+build2")
-        vr = _VersionRepr(v1)
-        assert vr.major() == "master"
-        assert vr.minor() == "master"
-        assert vr.patch() == "master"
-        assert vr.pre() == "master"
-        assert vr.build == "build2"
-        assert vr.stable() == "master"
-
-    def test_patch(self):
-        from conans.model.recipe_ref import Version
-        v1 = Version("1.2.3-alpha1+build2")
-        vr = _VersionRepr(v1)
-        assert vr.major() == "1.Y.Z"
-        assert vr.minor() == "1.2.Z"
-        assert vr.patch() == "1.2.3"
-        assert vr.pre() == "1.2.3-alpha1"
-        assert vr.build == "build2"
-        assert vr.stable() == "1.Y.Z"
-
-        v1 = Version("1.2.3+build2")
-        vr = _VersionRepr(v1)
-        self.assertEqual(vr.major(), "1.Y.Z")
-        self.assertEqual(vr.minor(), "1.2.Z")
-        self.assertEqual(vr.patch(), "1.2.3")
-        self.assertEqual(vr.pre(), "1.2.3")
-        self.assertEqual(vr.build, "build2")
-        self.assertEqual(vr.stable(), "1.Y.Z")
-
-        v1 = Version("0.2.3-alpha1+build2")
-        vr = _VersionRepr(v1)
-        self.assertEqual(vr.major(), "0.Y.Z")
-        self.assertEqual(vr.minor(), "0.2.Z")
-        self.assertEqual(vr.patch(), "0.2.3")
-        self.assertEqual(vr.pre(), "0.2.3-alpha1")
-        self.assertEqual(vr.build, "build2")
-        self.assertEqual(vr.stable(), "0.2.3-alpha1+build2")
-
-        v1 = Version("+build2")
-        vr = _VersionRepr(v1)
-        assert vr.major() == ""
-
-    def test_build(self):
-        from conans.model.recipe_ref import Version
-        v1 = Version("0.2.3-alpha1+build2")
-        vr = _VersionRepr(v1)
-        self.assertEqual(vr.build, "build2")
-        v2 = Version("0.2.3+b178")
-        vr = _VersionRepr(v2)
-        self.assertEqual(vr.build, "b178")
diff --git a/conans/test/unittests/model/versionrepr_test.py b/conans/test/unittests/model/versionrepr_test.py
new file mode 100644
--- /dev/null
+++ b/conans/test/unittests/model/versionrepr_test.py
@@ -0,0 +1,57 @@
+import unittest
+
+from conans.model.info import _VersionRepr
+from conans.model.version import Version
+
+
+class VersionReprTest(unittest.TestCase):
+
+    def test_text(self):
+        v1 = Version("master+build2")
+        vr = _VersionRepr(v1)
+        assert vr.major() == "master"
+        assert vr.minor() == "master"
+        assert vr.patch() == "master"
+        assert vr.pre() == "master"
+        assert vr.build == "build2"
+        assert vr.stable() == "master"
+
+    def test_patch(self):
+        v1 = Version("1.2.3-alpha1+build2")
+        vr = _VersionRepr(v1)
+        assert vr.major() == "1.Y.Z"
+        assert vr.minor() == "1.2.Z"
+        assert vr.patch() == "1.2.3"
+        assert vr.pre() == "1.2.3-alpha1"
+        assert vr.build == "build2"
+        assert vr.stable() == "1.Y.Z"
+
+        v1 = Version("1.2.3+build2")
+        vr = _VersionRepr(v1)
+        self.assertEqual(vr.major(), "1.Y.Z")
+        self.assertEqual(vr.minor(), "1.2.Z")
+        self.assertEqual(vr.patch(), "1.2.3")
+        self.assertEqual(vr.pre(), "1.2.3")
+        self.assertEqual(vr.build, "build2")
+        self.assertEqual(vr.stable(), "1.Y.Z")
+
+        v1 = Version("0.2.3-alpha1+build2")
+        vr = _VersionRepr(v1)
+        self.assertEqual(vr.major(), "0.Y.Z")
+        self.assertEqual(vr.minor(), "0.2.Z")
+        self.assertEqual(vr.patch(), "0.2.3")
+        self.assertEqual(vr.pre(), "0.2.3-alpha1")
+        self.assertEqual(vr.build, "build2")
+        self.assertEqual(vr.stable(), "0.2.3-alpha1+build2")
+
+        v1 = Version("+build2")
+        vr = _VersionRepr(v1)
+        assert vr.major() == ""
+
+    def test_build(self):
+        v1 = Version("0.2.3-alpha1+build2")
+        vr = _VersionRepr(v1)
+        self.assertEqual(vr.build, "build2")
+        v2 = Version("0.2.3+b178")
+        vr = _VersionRepr(v2)
+        self.assertEqual(vr.build, "b178")