From 017ad4a57312b38213fb8e73b671fcbd9815fe2f Mon Sep 17 00:00:00 2001 From: Ivan Pozdeev Date: Thu, 16 Jul 2026 10:19:06 +0300 Subject: [PATCH] Add pyenv-binary tests to CI * README: fix tests instructions * test/README: -duplicating and unnecessary stuff * Makefile: Build Docker images and replace bats link conditionally * Makefile: fix indent irregularity --- Makefile | 95 +++++++++++++++++++++++++++++--------------------- README.md | 9 ++--- test/README.md | 67 ++++++++--------------------------- 3 files changed, 74 insertions(+), 97 deletions(-) diff --git a/Makefile b/Makefile index 08bf4949..17175588 100644 --- a/Makefile +++ b/Makefile @@ -1,16 +1,21 @@ TEST_BATS_VERSION = v1.10.0 TEST_BASH_VERSIONS = 3.2.57 4.1.17 + TEST_UNIT_DOCKER_PREFIX = test-unit-docker TEST_UNIT_DOCKER_TARGETS = $(foreach bash,$(TEST_BASH_VERSIONS),$(addsuffix -$(bash),$(TEST_UNIT_DOCKER_PREFIX)) $(addsuffix -gnu-$(bash),$(TEST_UNIT_DOCKER_PREFIX))) -TEST_PLUGIN_DOCKER_PREFIX = test-plugin-docker -TEST_PLUGIN_DOCKER_TARGETS = $(foreach bash,$(TEST_BASH_VERSIONS),$(addsuffix -$(bash),$(TEST_PLUGIN_DOCKER_PREFIX)) $(addsuffix -gnu-$(bash),$(TEST_PLUGIN_DOCKER_PREFIX))) + +TEST_PYTHON_BUILD_DOCKER_PREFIX = test-python-build-docker +TEST_PYTHON_BUILD_DOCKER_TARGETS = $(foreach bash,$(TEST_BASH_VERSIONS),$(addsuffix -$(bash),$(TEST_PYTHON_BUILD_DOCKER_PREFIX)) $(addsuffix -gnu-$(bash),$(TEST_PYTHON_BUILD_DOCKER_PREFIX))) + +TEST_BINARY_DOCKER_PREFIX = test-binary-docker +TEST_BINARY_DOCKER_TARGETS = $(foreach bash,$(TEST_BASH_VERSIONS),$(addsuffix -$(bash),$(TEST_BINARY_DOCKER_PREFIX)) $(addsuffix -gnu-$(bash),$(TEST_BINARY_DOCKER_PREFIX))) + TEST_BATS_IMAGE_PREFIX = test-pyenv-docker-image TEST_BATS_IMAGE_TARGETS = $(foreach bash,$(TEST_BASH_VERSIONS),$(addsuffix -$(bash),$(TEST_BATS_IMAGE_PREFIX)) $(addsuffix -gnu-$(bash),$(TEST_BATS_IMAGE_PREFIX))) -.PHONY: -test-docker: $(TEST_UNIT_DOCKER_PREFIX) $(TEST_PLUGIN_DOCKER_PREFIX) +.PHONY: test-docker +test-docker: $(TEST_UNIT_DOCKER_PREFIX) $(TEST_PYTHON_BUILD_DOCKER_PREFIX) $(TEST_BINARY_DOCKER_PREFIX) -# Run all unit test under bats docker .PHONY: $(TEST_UNIT_DOCKER_PREFIX) $(TEST_UNIT_DOCKER_PREFIX): $(TEST_UNIT_DOCKER_TARGETS) @@ -31,23 +36,22 @@ $(TEST_UNIT_DOCKER_TARGETS): $(TEST_UNIT_DOCKER_PREFIX)-% : $(TEST_BATS_IMAGE_PR -u "$$(id -u $$(whoami)):$$(id -g $$(whoami))" \ $${BATS_TEST_FILTER:+-e BATS_TEST_FILTER="$${BATS_TEST_FILTER}"} \ $${BATS_FILE_FILTER:+-e BATS_FILE_FILTER="$${BATS_FILE_FILTER}"} \ - $${CI+-e CI="$${CI}"} \ - $(INTERACTIVE) \ + $${CI+-e CI="$${CI}"} \ + $(INTERACTIVE) \ $(DOCKER_IMAGE):$(DOCKER_TAG) \ test/run -# Run all plugin test under bats docker -.PHONY: $(TEST_PLUGIN_DOCKER_PREFIX) -$(TEST_PLUGIN_DOCKER_PREFIX): $(TEST_PLUGIN_DOCKER_TARGETS) +.PHONY: $(TEST_PYTHON_BUILD_DOCKER_PREFIX) +$(TEST_PYTHON_BUILD_DOCKER_PREFIX): $(TEST_PYTHON_BUILD_DOCKER_TARGETS) # Run each plugin test under bats docker -.PHONY: $(TEST_PLUGIN_DOCKER_TARGETS) -$(TEST_PLUGIN_DOCKER_TARGETS): DOCKER_IMAGE = $(TEST_BATS_IMAGE_PREFIX) -$(TEST_PLUGIN_DOCKER_TARGETS): GNU = $(if $(findstring -gnu-,$@),True,False) -$(TEST_PLUGIN_DOCKER_TARGETS): BASH = $(filter $(TEST_BASH_VERSIONS),$(subst -, ,$@)) -$(TEST_PLUGIN_DOCKER_TARGETS): DOCKER_TAG = bash-$(BASH)-gnu-$(GNU) -$(TEST_PLUGIN_DOCKER_TARGETS): INTERACTIVE = $(if $(findstring true,$(CI)),,-ti) -$(TEST_PLUGIN_DOCKER_TARGETS): $(TEST_PLUGIN_DOCKER_PREFIX)-% : $(TEST_BATS_IMAGE_PREFIX)-% +.PHONY: $(TEST_PYTHON_BUILD_DOCKER_TARGETS) +$(TEST_PYTHON_BUILD_DOCKER_TARGETS): DOCKER_IMAGE = $(TEST_BATS_IMAGE_PREFIX) +$(TEST_PYTHON_BUILD_DOCKER_TARGETS): GNU = $(if $(findstring -gnu-,$@),True,False) +$(TEST_PYTHON_BUILD_DOCKER_TARGETS): BASH = $(filter $(TEST_BASH_VERSIONS),$(subst -, ,$@)) +$(TEST_PYTHON_BUILD_DOCKER_TARGETS): DOCKER_TAG = bash-$(BASH)-gnu-$(GNU) +$(TEST_PYTHON_BUILD_DOCKER_TARGETS): INTERACTIVE = $(if $(findstring true,$(CI)),,-ti) +$(TEST_PYTHON_BUILD_DOCKER_TARGETS): $(TEST_PYTHON_BUILD_DOCKER_PREFIX)-% : $(TEST_BATS_IMAGE_PREFIX)-% $(info Running test with docker image '$(DOCKER_IMAGE):$(DOCKER_TAG)') docker run \ --init \ @@ -55,11 +59,33 @@ $(TEST_PLUGIN_DOCKER_TARGETS): $(TEST_PLUGIN_DOCKER_PREFIX)-% : $(TEST_BATS_IMAG -v /etc/passwd:/etc/passwd:ro \ -v /etc/group:/etc/group:ro \ -u "$$(id -u $$(whoami)):$$(id -g $$(whoami))" \ - $${CI+-e CI="$${CI}"} \ - $(INTERACTIVE) \ + $${CI+-e CI="$${CI}"} \ + $(INTERACTIVE) \ $(DOCKER_IMAGE):$(DOCKER_TAG) \ bats $${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} plugins/python-build/test/$${BATS_FILE_FILTER} +.PHONY: $(TEST_BINARY_DOCKER_PREFIX) +$(TEST_BINARY_DOCKER_PREFIX): $(TEST_BINARY_DOCKER_TARGETS) + +.PHONY: $(TEST_BINARY_DOCKER_TARGETS) +$(TEST_BINARY_DOCKER_TARGETS): DOCKER_IMAGE = $(TEST_BATS_IMAGE_PREFIX) +$(TEST_BINARY_DOCKER_TARGETS): GNU = $(if $(findstring -gnu-,$@),True,False) +$(TEST_BINARY_DOCKER_TARGETS): BASH = $(filter $(TEST_BASH_VERSIONS),$(subst -, ,$@)) +$(TEST_BINARY_DOCKER_TARGETS): DOCKER_TAG = bash-$(BASH)-gnu-$(GNU) +$(TEST_BINARY_DOCKER_TARGETS): INTERACTIVE = $(if $(findstring true,$(CI)),,-ti) +$(TEST_BINARY_DOCKER_TARGETS): $(TEST_BINARY_DOCKER_PREFIX)-% : $(TEST_BATS_IMAGE_PREFIX)-% + $(info Running test with docker image '$(DOCKER_IMAGE):$(DOCKER_TAG)') + docker run \ + --init \ + -v $(PWD):/code:ro \ + -v /etc/passwd:/etc/passwd:ro \ + -v /etc/group:/etc/group:ro \ + -u "$$(id -u $$(whoami)):$$(id -g $$(whoami))" \ + $${CI+-e CI="$${CI}"} \ + $(INTERACTIVE) \ + $(DOCKER_IMAGE):$(DOCKER_TAG) \ + bats $${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} plugins/pyenv-binary/test/$${BATS_FILE_FILTER} + # Build all images needed for bats under docker .PHONY: $(TEST_BATS_IMAGE_PREFIX) $(TEST_BATS_IMAGE_PREFIX): $(TEST_BATS_IMAGE_TARGETS) @@ -71,7 +97,7 @@ $(TEST_BATS_IMAGE_TARGETS): GNU = $(if $(findstring -gnu-,$@),True,False) $(TEST_BATS_IMAGE_TARGETS): BASH = $(filter $(TEST_BASH_VERSIONS),$(subst -, ,$@)) $(TEST_BATS_IMAGE_TARGETS): DOCKER_TAG = bash-$(BASH)-gnu-$(GNU) $(TEST_BATS_IMAGE_TARGETS): - $(info Building docker image '$(DOCKER_IMAGE):$(DOCKER_TAG)') + if [ -z "$$(docker images -q '$(DOCKER_IMAGE):$(DOCKER_TAG)')" ]]; then \ docker build \ --quiet \ -f "$(PWD)/test/Dockerfile" \ @@ -79,41 +105,32 @@ $(TEST_BATS_IMAGE_TARGETS): --build-arg BASH="$(BASH)" \ --build-arg BATS_VERSION="$(TEST_BATS_VERSION)" \ -t $(DOCKER_IMAGE):$(DOCKER_TAG) \ - ./ + ./ ; \ + fi -.PHONY: test test-build test-unit test-plugin +.PHONY: test test-unit test-python-build test-binary # Do not pass in user flags to build tests. unexport PYTHON_CFLAGS unexport PYTHON_CONFIGURE_OPTS -test: test-unit test-plugin +test: test-unit test-python-build test-binary test-unit: bats PATH="./bats/bin:$$PATH" test/run -test-plugin: bats +test-python-build: bats cd plugins/python-build && $(PWD)/bats/bin/bats $${CI:+--tap} $${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} test/$${BATS_FILE_FILTER} -PYTHON_BUILD_ROOT := $(CURDIR)/plugins/python-build -PYTHON_BUILD_OPTS ?= --verbose -PYTHON_BUILD_VERSION ?= 3.8-dev -PYTHON_BUILD_TEST_PREFIX ?= $(PYTHON_BUILD_ROOT)/test/build/tmp/dist - -test-build: - $(RM) -r $(PYTHON_BUILD_TEST_PREFIX) - $(PYTHON_BUILD_ROOT)/bin/python-build $(PYTHON_BUILD_OPTS) $(PYTHON_BUILD_VERSION) $(PYTHON_BUILD_TEST_PREFIX) - [ -e $(PYTHON_BUILD_TEST_PREFIX)/bin/python ] - $(PYTHON_BUILD_TEST_PREFIX)/bin/python -V - [ -e $(PYTHON_BUILD_TEST_PREFIX)/bin/pip ] - $(PYTHON_BUILD_TEST_PREFIX)/bin/pip -V +test-binary: bats + cd plugins/pyenv-binary && $(PWD)/bats/bin/bats $${CI:+--tap} $${BATS_TEST_FILTER:+--filter "$${BATS_TEST_FILTER}"} test/$${BATS_FILE_FILTER} .SECONDARY: bats-$(TEST_BATS_VERSION) bats-$(TEST_BATS_VERSION): - rm -rf bats - ln -sf bats-$(TEST_BATS_VERSION) bats git clone --depth 1 --branch $(TEST_BATS_VERSION) https://github.com/bats-core/bats-core.git bats-$(TEST_BATS_VERSION) .PHONY: bats bats: bats-$(TEST_BATS_VERSION) - ln -sf bats-$(TEST_BATS_VERSION) bats + if [ \( ! -L bats \) -o \( "x$$(readlink bats)" != "xbats-$(TEST_BATS_VERSION)" \) ]; then \ + rm -rf bats; ln -s bats-$(TEST_BATS_VERSION) bats; \ + fi diff --git a/README.md b/README.md index 2872e7e0..7ff5898d 100644 --- a/README.md +++ b/README.md @@ -837,13 +837,10 @@ e.g. `~/.pyenv --install bash`. ## Development The pyenv source code is [hosted on -GitHub](https://github.com/pyenv/pyenv). It's clean, modular, -and easy to understand, even if you're not a shell hacker. +GitHub](https://github.com/pyenv/pyenv). -Tests are executed using [Bats](https://github.com/bats-core/bats-core): - - bats test - bats/test/.bats +Tests are executed using [Bats](https://github.com/bats-core/bats-core). +See the [tests README](test/README.md) for details. ### Contributing diff --git a/test/README.md b/test/README.md index 682702e2..e8ba5e18 100644 --- a/test/README.md +++ b/test/README.md @@ -15,62 +15,25 @@ Under the hood, `pyenv` test suites use `bats` as a test framework and are run o - `test` - Run the whole test suite on the local host - `test-docker` - - Run the whole test suite on docker - - Some volumes are used in read-only mode + - Run the whole test suite in Docker (in all environments) - `test-unit` - - Run the unit test -- `test-plugin` - - Run the plugin test -- `test-unit-docker-[BASH_VERSION]` - - Run the unit test under **official** bash docker container (alpine/busybox) with the specified bash version if present is in the `Makefile` - - Some volumes are used in read-only mode -- `test-unit-docker-gnu-[BASH_VERSION]` - - Run the unit test under **official** bash docker container (alpine/busybox), completed by **GNU Tools**, with the specified bash version if present is in the `Makefile` - - Some volumes are used in read-only mode -- `test-plugin-docker-[BASH_VERSION]` - - Run the plugin test under **official** bash docker container (alpine/busybox), completed by **GNU Tools**, with the specified bash version if present is in the `Makefile` - - Some volumes are used in read-only mode -- `test-plugin-docker-gnu-[BASH_VERSION]` - - Run the plugin test under **official** bash docker container (alpine/busybox), completed by **GNU Tools**, with the specified bash version if present is in the `Makefile` - - Some volumes are used in read-only mode + - Run core tests +- `test-python-build` + - Run Python-Build tests +- `test-binary` + - Run Pyenv-Binary tests +- `test-*-docker` + - Run the corresponding test suite in Docker +- `test-*-docker-[BASH_VERSION]`, `test-*-docker-gnu-[BASH_VERSION]` + - Run the corresponding test suite in the official Bash Docker container (alpine/busybox) + against either Busybox tools or GNU tools, with the specified Bash version + among those listed in the `Makefile` ## Targeting specific test / test file - By setting some environment variables, it is possible to filtering which test and/or test file who will be tested with bats + By setting some environment variables, it is possible to filter which test and/or test file will be run - `BATS_FILE_FILTER` - - - Run test only with the specified file - + - Run tests from the specified file - `BATS_TEST_FILTER` - - Run test only who corresponding to the filter provided - - -### Examples - -```bash - $ BATS_TEST_FILTER=".*installed.*" BATS_FILE_FILTER="build.bats" make test-plugin-docker-gnu-3.2.57 - build.bats - ✓ yaml is installed for python - ✓ homebrew is used in Linux if Pyenv is installed with Homebrew - ✓ homebrew is not used in Linux if Pyenv is not installed with Homebrew - - 3 tests, 0 failures - - $ BATS_TEST_FILTER=".*installed.*" BATS_FILE_FILTER="build.bats" make test-plugin - build.bats - ✓ yaml is installed for python - ✓ homebrew is used in Linux if Pyenv is installed with Homebrew - ✓ homebrew is not used in Linux if Pyenv is not installed with Homebrew - - 3 tests, 0 failures -``` - - - -## Writing test - -To be reproducible, each test use/should use its own `TMPDIR` . -It's achieved by using the environment variable `BATS_TEST_TMPDIR` provided by bats that is automatically deleted at the end of each test. More info [here](https://bats-core.readthedocs.io/en/stable/writing-tests.html#special-variables) - -Another variable who could be used to source some file who need to be tested is `BATS_TEST_DIRNAME` who point to the directory in which the bats test file is located. \ No newline at end of file + - Run tests with the names corresponding to the filter