Repository: conan-io/conan

Issue:
[question] How do I set/change the location of the test_package information
### What is your question?

# How do I set/change the location of the test_package information?

The standard conan location for it's `test_package` folder breaks my company's standards. All tests must reside under an appropriately named folder rooted under `tests`

For example:

```
tests/unit
tests/integration
tests/network
```

I want to use conan's test_package ability, but I'll need to move it to something like `tests/package` or `tests/conan_packaging`, etc.

How can I achieve this?

I was thinking it might be in the [`self.cpp_info`][1] section but I don't see a way to change that mapping.

I did find the [`cmake_layout:test_folder`][2], however, that appears to change where the test code is built, not change the location of the `test_package`




[1]: https://docs.conan.io/2/reference/conanfile/methods/package_info.html#cpp-info-library-and-build-information
[2]: https://docs.conan.io/2/reference/tools/cmake/cmake_layout.html#cmake-layout:~:text=tools.cmake.cmake_layout%3Atest_folder

### Have you read the CONTRIBUTING guide?

- [X] I've read the CONTRIBUTING guide


Discussion:
Hi @RochaStratovan 

the ``test_package`` folder can be defined in command line: ``conan create . --test-folder=path/to/my/test_package``

The conf ``tools.cmake.cmake_layout:test_folder`` is only about the "build" of the ``test_package``, not about the location of the ``test_package`` itself.
Oh. Nuts. So this is something that my devs would have to remember to add manually to the `conan create` or `conan export-pkg` CLI entries? That's unfortunate.

Can a feature be added to allow the `test_package` location to be identified in the `conanfile.py` file?
> Can a feature be added to allow the test_package location to be identified in the conanfile.py file?

yes, this makes sense, lets add it.




Patch:
diff --git a/conan/cli/commands/create.py b/conan/cli/commands/create.py
index 36b96788264..d5b2e186eea 100644
--- a/conan/cli/commands/create.py
+++ b/conan/cli/commands/create.py
@@ -40,7 +40,6 @@ def create(conan_api, parser, *args):
 
     cwd = os.getcwd()
     path = conan_api.local.get_conanfile_path(args.path, cwd, py=True)
-    test_conanfile_path = _get_test_conanfile_path(args.test_folder, path)
     overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None
     lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile,
                                                conanfile_path=path,
@@ -98,6 +97,9 @@ def create(conan_api, parser, *args):
         lockfile = conan_api.lockfile.update_lockfile(lockfile, deps_graph, args.lockfile_packages,
                                                       clean=args.lockfile_clean)
 
+    test_package_folder = getattr(conanfile, "test_package_folder", None) \
+        if args.test_folder is None else args.test_folder
+    test_conanfile_path = _get_test_conanfile_path(test_package_folder, path)
     # If the user provide --test-missing and the binary was not built from source, skip test_package
     if args.test_missing and deps_graph.root.dependencies\
             and deps_graph.root.dependencies[0].dst.binary != BINARY_BUILD:


Test patch:
diff --git a/conans/test/integration/layout/test_layout_generate.py b/conans/test/integration/layout/test_layout_generate.py
index 7548f078882..0fdbbe8ef46 100644
--- a/conans/test/integration/layout/test_layout_generate.py
+++ b/conans/test/integration/layout/test_layout_generate.py
@@ -125,3 +125,33 @@ def test(self):
             "test_package/conanfile.py": conanfile})
     c.run("create .")
     assert f"build_folder in test_package: True" in c.out
+
+
+class TestCustomTestPackage:
+    def test_custom_test_package(self):
+        c = TestClient(light=True)
+        conanfile = GenConanfile("pkg", "0.1").with_class_attribute('test_package_folder="mytest"')
+        c.save({"conanfile.py": conanfile,
+                "mytest/conanfile.py": GenConanfile().with_test("self.output.info('MYTEST!')"),
+                "mytest2/conanfile.py": GenConanfile().with_test("self.output.info('MYTEST2!')")})
+        c.run("create .")
+        assert "MYTEST!" in c.out
+        c.run("create . -tf=mytest2")
+        assert "MYTEST2!" in c.out
+
+    def test_custom_test_package_subfolder(self):
+        c = TestClient(light=True)
+        conanfile = GenConanfile("pkg", "0.1").with_class_attribute('test_package_folder="my/test"')
+        c.save({"pkg/conanfile.py": conanfile,
+                "pkg/my/test/conanfile.py": GenConanfile().with_test("self.output.info('MYTEST!')")})
+        c.run("create pkg")
+        assert "MYTEST!" in c.out
+
+    def test_custom_test_package_sibling(self):
+        c = TestClient(light=True)
+        conanfile = GenConanfile("pkg", "0.1").with_class_attribute(
+            'test_package_folder="../my/test"')
+        c.save({"pkg/conan/conanfile.py": conanfile,
+                "pkg/my/test/conanfile.py": GenConanfile().with_test("self.output.info('MYTEST!')")})
+        c.run("create pkg/conan")
+        assert "MYTEST!" in c.out