-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How do I run Test from within Docker? #11
Comments
No idea. I'm not sure it's possible right now though: nvim-neotest/neotest#89 |
Oh.. then I'll wait |
Would it make sense to make a bash script or an alias that calls phpunit from docker as a workaround? |
@phaberest |
I found a fork from @saifulapm (https://github.com/saifulapm/neotest-phpunit) that helped a bit, but I am not proficient in Lua so I'm not yet able to get to a point of success I made my own fork https://github.com/phaberest/neotest-phpunit that is able to call phpunit from laravel sail (and it would be easy to add docker as well, we can just check if there's a The problem so far is that I'm not able to remove my local path from the path of the file when launching a test. I don't even think it is necessary to remap to the path that the file has inside docker, because it is not necessary to use the full path if we use This is basically what I tried to do with a goofy hardcoded string https://github.com/phaberest/neotest-phpunit/blame/1d09587961819d0fd5fe2847845d58323791c4e4/lua/neotest-phpunit/init.lua#L88 I'll give it another try in the next days and eventually submit a PR to this repo once it works, but as stated in #8 it would need to be generalised a bit using config parameters |
Another alternative could be to use https://github.com/nvim-neotest/neotest-vim-test instead, but I'm not sure it can work either |
You don't need to fork the plugin to add that functionality. As per the readme, you can specify the phpunit command to run in a function. |
Doing it that way triggers the error mentioned in the first post of this issue |
cb4808c shuld be able to solve the issue, thank you @olimorris |
Happy to accept any PRs for more user configurable options btw |
sounds nice but how? local neotest = require("neotest")
neotest.setup({
adapters = {
require('neotest-phpunit')({
phpunit_cmd = function()
return 'docker exec -it $(docker ps -n=-1 -q --filter name=phpfpm --format="{{.ID}}") vendor/bin/phpunit'
end
}),
},
}) nor like this: (just runs forever. no errors) local neotest = require("neotest")
neotest.setup({
adapters = {
require('neotest-phpunit')({
phpunit_cmd = function()
return "./run-tests.sh"
end
}),
},
})
run-tests.sh #!/bin/bash
docker exec -it $(docker ps -n=-1 -q --filter name=phpfpm --format="{{.ID}}") vendor/bin/phpunit |
I'll give it a go tonight and give you an update 🙌🏻 |
Tried briefly, couple of issues:
@Artem-Schander your issue most likely is with the -it parameter, which makes the command interactive? The command can be set like this, which works, except that the path wont work correctly:
|
@haringsrob
The path in which neotest tries to find the file ist my local path, not the one inside the container. FYI local neotest = require("neotest")
neotest.setup({
adapters = {
require('neotest-phpunit')({
phpunit_cmd = function()
return {
"docker",
"exec",
"5a386e04b1f6", -- image ID
"php",
"vendor/bin/phpunit"
}
end,
}),
},
}) if i try it with the more dynamic approach
|
Based on some information here: nvim-neotest/neotest#89 I played a bit and made the following runner script: #!/bin/bash
# Customize the following:
# - escaped_path: absolute local path to your project
# - container: name of your docker container
escaped_path="\/Volumes\/Sites\/YOUR PROJECTPATH\/" # Be careful to properly escape this
containerName=REPLACE CONTAINER NAME
# WARN: This will break if flags other than -o and -f are added in neotest-rspec
while getopts o:f: flag; do
# This deliberately does not handle all arguments
# shellcheck disable=SC2220
# shellcheck disable=SC2213
case "${flag}" in
o) output_path=${OPTARG} ;;
esac
done
for i in "$@"; do
case $i in
--log-junit=*)
localPath="${i#*=}"
shift
;;
*)
;;
esac
done
replace="/var/folders"
replaceWith="/var/www/vendor/neotest-test-output"
replaceWithLocal="./vendor/neotest-test-output"
# Strip local path from test paths sent to container
args=("${@/$escaped_path/}")
args=${args/$replace/$replaceWith}
dockerPath=${localPath/$replace/$replaceWith}
container=$(docker ps -n=-1 --filter name=${containerName} --format="{{.ID}}")
# Run the tests
docker exec "$container" touch "${dockerPath}"
docker exec "$container" vendor/bin/phpunit "${args[@]}"
cp ${localPath/$replace/$replaceWithLocal} ${localPath} While it does run the script perfectly, and it displays the output correctly, it does not mark the test as passed. Not sure why. |
thank you @haringsrob, I'll give it a go later |
#!/bin/bash
# Customize the following:
# - escaped_path: absolute local path to your project
# - container: name of your docker container
escaped_path="\/Volumes\/Sites\/YOUR PROJECTPATH\/" # Be careful to properly escape this
containerName=REPLACE CONTAINER NAME
argsCopy=${@}
for i in $argsCopy; do
case $i in
--log-junit=*)
localPath="${i#*=}"
;;
*)
;;
esac
done
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
--filter)
filterVal="$2"
shift # past argument
shift # past value
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
replace="/var/folders"
replaceWith="/var/www/vendor/neotest-test-output"
replaceWithLocal="./vendor/neotest-test-output"
# Strip local path from test paths sent to container
args=${argsCopy/$escaped_path/"/var/www/"}
args=${args/$replace/$replaceWith}
args=${args/$filterVal/\'/$filterVal/\'}
args=${args/"--filter "/"--filter "}
dockerPath=${localPath/$replace/$replaceWith}
container=$(docker ps -n=-1 --filter name=${containerName} --format="{{.ID}}")
echo ${args}
# Run the tests
docker exec "$container" touch "${dockerPath}"
docker exec "$container" bash -c "vendor/bin/phpunit ${args[@]}"
cp ${localPath/$replace/$replaceWithLocal} ${localPath} With fixes for filter and allow to run full suite. |
@olimorris not sure why it is not parsing the result correctly. I double checked and the junit files are where it is expected to be (on the host system). |
@haringsrob - we recently added Docker support in my other Neotest adapter, here. I'd be open to any PR that could add this functionality. |
For my own and others, the issue was that it did not have the correct path in the junit file. This I solved with:
As the last line in the script above. |
I am using docker-compose and I am facing this issue
is there any way to replace regarding with this |
On that Base I have created one more script for random docker dir Project Dir we take by .git folder So for use: require("neotest").setup {
adapters = {
require "neotest-phpunit" {
root_files = { "composer.json", "phpunit.xml", "phpunit.xml.dist", ".github" },
filter_dirs = { "vendor" },
env = {
CONTAINER = "container_name",
REMOTE_PHPUNIT_BIN = "bin/phpunit",
},
phpunit_cmd = function()
return "/usr/local/bin/dphpunit"
end,
},
},
} Where:
Run test bash #!/bin/sh
# Customize the following:
containerName=$CONTAINER
phpunitPath=$REMOTE_PHPUNIT_BIN
# detect local path and remove from args
argsInput=${@}
runFile=$(echo $argsInput| awk '{print $1}')
phpTestPath=$(dirname "$runFile")
pushd $phpTestPath > /dev/null
projectPath="$(git rev-parse --show-toplevel)"
pushd > /dev/null
## detect test result output
for i in $argsInput; do
case $i in
--log-junit=*)
outputPath="${i#*=}"
;;
*)
;;
esac
done
# replace with local
args=("${argsInput/$projectPath\//}")
# replace strange line with (data set .*)
args=("${args//(*}")
# Detect path
container=$(docker ps -n=-1 --filter name=$containerName --format="{{.ID}}")
dockerPath=$(docker inspect --format {{.Config.WorkingDir}} $container)
## debug
# echo "Params: "${args[@]}
# echo "Docker: "$dockerPath
# echo "Local: "$projectPath
# echo "Result: "$outputPath
# Run the tests
docker exec -i $container php -d memory_limit=-1 $phpunitPath ${args[@]}
# copy results
docker cp -a "$container:$outputPath" "$outputPath"|- &> /dev/null
# replace docker path to locals
sed -i '_' "s#$dockerPath#$projectPath#g" $outputPath
|
just to say that I tested @kilatib code and it worked perfect. in case someone is using lazyvim the config will be like this {
"nvim-neotest/neotest",
dependencies = {
"olimorris/neotest-phpunit",
},
opts = {
adapters = {
["neotest-phpunit"] = {
env = {
CONTAINER = "your_container_name",
REMOTE_PHPUNIT_BIN = "bin/phpunit",
},
phpunit_cmd = function()
return "the/bash/file/above"
end,
},
},
},
},
thank you @kilatib <3 |
Hi everyone, I'm sorry to disturb the closed issue. It seems that junit is not able to create a directory (which already exists). I dont believe it to be related to permissions. PHPUnit 9.6.19 by Sebastian Bergmann and contributors.
Directory "/var/folders/k7/mpvywsws2y55tqb4x4mtym5h0000gn/T/nvim.artemschander/arWc8a" was not created
Error response from daemon: Could not find the file /var/folders/k7/mpvywsws2y55tqb4x4mtym5h0000gn/T/nvim.artemschander/arWc8a/77 in container d8e1cfc02e67
sed: /var/folders/k7/mpvywsws2y55tqb4x4mtym5h0000gn/T/nvim.artemschander/arWc8a/77: No such file or directory I tinkered a bit and was able to work around this problem by replacing Here is my take on it: #!/bin/sh
# Customize the following:
containerName=$CONTAINER
phpunitPath=$REMOTE_PHPUNIT_BIN
# detect local path and remove from args
argsInput=${@}
runFile=$(echo $argsInput| awk '{print $1}')
phpTestPath=$(dirname "$runFile")
pushd $phpTestPath > /dev/null
projectPath="$(git rev-parse --show-toplevel)"
pushd > /dev/null
## detect test result output
for i in $argsInput; do
case $i in
--log-junit=*)
outputPath="${i#*=}"
;;
*)
;;
esac
done
# replace with local
args=("${argsInput/$projectPath\//}")
# replace strange line with (data set .*)
args=("${args//(*}")
# sed -i '' "s|${outputPath}|foo|g" ${args[@]}
# Detect path
container=$(docker ps -n=-1 --filter name=$containerName --format="{{.ID}}")
dockerPath=$(docker inspect --format {{.Config.WorkingDir}} $container)
# replace docker path to locals
result="phpunit-result.xml"
args=${args//$outputPath/$result}
## debug
# echo "Params: "${args[@]}
# echo "Docker: "$dockerPath
# echo "Local: "$projectPath
# echo "Result: "$outputPath
# echo "docker exec -i "$container" php -d memory_limit=-1 "$phpunitPath" "${args[@]}
# Run the tests
docker exec -i $container php -d memory_limit=-1 $phpunitPath ${args[@]}
# copy results
# docker cp -a "$container:$outputPath" "$outputPath"|- &> /dev/null
docker cp -a "$container:$dockerPath/$result" "$projectPath/$result"|- &> /dev/null
# replace docker path to locals
# sed -i '_' "s#$dockerPath#$projectPath#g" $outputPath
sed -i '_' "s#$dockerPath#$projectPath#g" "$projectPath/$result" I have no idea what the last two commands meant to do exactly, so i believe i have done something wrong there |
@Artem-Schander This error happens when the docker container where you run tests is down |
@kilatib strange, it was/is definitely not down. If i change the shell script to make docker write the junit output into the project dir (on host) then the error disappears and the tests are running correctly. but then the # copy results
# docker cp -a "$container:$outputPath" "$outputPath"|- &> /dev/null
docker cp -a "$container:$dockerPath/$result" "$projectPath/$result"|- &> /dev/null
# replace docker path to locals
# sed -i '_' "s#$dockerPath#$projectPath#g" $outputPath
sed -i '_' "s#$dockerPath#$projectPath#g" "$projectPath/$result" |
@Artem-Schander Do you have permission to write into that directory inside your docker container? |
Yes. That was the first i checked. The permissions are the same for both directories. That one works:
That one doesn't
Also it's worth mentioning that the first one does not work if i use absolute paths. It says "Directory was not created" regardless that the directory already exists. It seems that the issue lays in absolute paths |
@Artem-Schander, please pay attention to that version of my script I did not post it here here I use a relative path inside container, also pay attention that I set path to PHPUnit inside the container dynamically
|
sadly this does not solve my issue. |
It is because of the path out of a project that's why it not replaced.
It still seems to me that your docker container does not allow me to write to |
I'm really sorry to bother you and every one subscribed to this issue. I feel dumb but I don't get at all what you mean.
what does that mean? what path?
every time i change the
what do you mean by that? I'm at a point where it's about to get too much hustle. I think I will go back to vim-test yet another time. I don't get what I am making wrong and why it is such a pain to get it working. It's sad. Maybe it would help to understand what exactly happens or need to happen. I have the following sutuation.. the shell script results (among others) in the following command.
this does not work on my machine, but seems to be not wrong. phpunit is advised to put a junit log file named I assume that this is some kind of a temporary directory for nvim where Somewhat like this:
Or maybe there is even a way to tell neotest that the junit log file is somewhere else? I mean the only issue I am left with is the wrong |
@Artem-Schander , My Idea was that probably into your container is not allowed to create any dirs out of your PHP project dir. What is the difference in your example with what neotest is called - you create result XML inside your PHP project dir where you have permission to write data. The problem with Neotest is that after result XML is created under your project it not appeared to dir where neotest is waiting for it. So, the solution for you is create it locally as you do in your example and then to copy it into the path which is expected by neotest For that script please update 3 variables:
|
Nice. thank you for all the help. it works now. I had to make some adjustments though. Here is the final # Customize the following:
containerName=$CONTAINER
phpunitPath=$REMOTE_PHPUNIT_BIN
# detect local path and remove from args
localPhpUnitResultPath='/tmp/phpunit-result.xml'
argsInput=${@}
runFile=$(echo $argsInput| awk '{print $1}')
phpTestPath=$(dirname "$runFile")
pushd $phpTestPath > /dev/null
projectPath="$(git rev-parse --show-toplevel)"
pushd > /dev/null
subPath=$(awk -F '/vendor/' '{print $1}' <<< $projectPath)
# containerName=$(sed 's#.*/##' <<< $subPath | sed s/-/_/g)
## detect test result output
for i in $argsInput; do
case $i in
--log-junit=*)
outputPath="${i#*=}"
;;
*)
;;
esac
done
# replace with local
args=("${argsInput/$subPath\//}")
args=("${args//(*}")
# Detect path
container=$(docker ps -n=-1 --filter name=$containerName --format="{{.ID}}")
phpunitPath=$(docker exec -it $container /bin/bash -c "if [ -f vendor/bin/phpunit ]; then echo vendor/bin/phpunit; else echo bin/phpunit; fi" | tr -d '\r')
execPath=$(docker exec -it $container /bin/bash -c "if [ -f /bin/sh ]; then echo /bin/sh; else echo /bin/bash; fi" | tr -d '\r')
dockerPath=$(docker inspect --format {{.Config.WorkingDir}} $container)
## debug
# echo "Raw ARGS: "${@}
# echo "Params: "${args[@]}
# echo "Docker: "$dockerPath
# echo "Local: "$projectPath
# echo "Result: "$outputPath
# echo "docker exec -i "$container" php -d memory_limit=-1 "$phpunitPath" "${args[@]}
# Run the tests
docker exec -it $container $execPath -c "SYMFONY_DEPRECATIONS_HELPER=weak $phpunitPath -d memory_limit=-1 -d xdebug.idekey=deliver-be ${args} --log-junit=${localPhpUnitResultPath}"
# docker exec -it $container $phpunitPath -d memory_limit=-1 ${args[@]}
# copy results
docker cp -a "$container:$localPhpUnitResultPath" "$outputPath"|- &> /dev/null
# replace docker path to locals
sed -i '_' "s#$dockerPath#$projectPath#g" $outputPath |
Hey @kilatib I am trying to make this work with codeception, But unfurtunally it just generate inside of it is the output <?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="App\Tests.Unit" tests="1" assertions="1" errors="0" failures="0" skipped="0" useless="0" time="0.007705">
<testsuite name="App\Tests\Unit\MeasurementValues\Domain\Mapper\MeasurementMapperTest" file="/app/tests/Unit/MeasurementValues/Domain/Mapper/MeasurementMapperTest.php" tests="1" assertions="1" errors="0" failures="0" skipped="0" useless="0" time="0.007705">
<testcase name="testPassObjectToArray" class="App\Tests\Unit\MeasurementValues\Domain\Mapper\MeasurementMapperTest" file="/app/tests/Unit/MeasurementValues/Domain/Mapper/MeasurementMapperTest.php" time="0.007705" assertions="1"/>
</testsuite>
</testsuite>
</testsuites> then I changed this line
But the icons keep red, do you have any idea? Edit just to compare codeception --phpunit-xml <?xml version="1.0" encoding="utf-8"?>
<testsuites>
<testsuite name="app\tests.unit" tests="1" assertions="2" errors="0" failures="0" skipped="0" useless="0" time="0.019728">
<testsuite name="app\tests\unit\measurementvalues\infrastructure\queue\task\measurementarchivingtasktest" file="/app/tests/unit/measurementvalues/infrastructure/queue/task/measurementarchivingtasktest.php" tests="1" assertions="2" errors="0" failures="0" skipped="0" useless="0" time="0.019728">
<testcase name="testcallmethodtogeneratefile" class="app\tests\unit\measurementvalues\infrastructure\queue\task\measurementarchivingtasktest" file="/app/tests/unit/measurementvalues/infrastructure/queue/task/measurementarchivingtasktest.php" time="0.019728" assertions="2"/>
</testsuite>
</testsuite>
</testsuites> codeception --xml <?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<testsuite name="App\Tests.Unit" tests="1" assertions="2" errors="0" failures="0" skipped="0" useless="0" time="0.024393">
<testcase name="testCallMethodToGenerateFile" class="App\Tests\Unit\MeasurementValues\Infrastructure\Queue\Task\MeasurementArchivingTaskTest" file="/app/tests/Unit/MeasurementValues/Infrastructure/Queue/Task/MeasurementArchivingTaskTest.php" time="0.024393" assertions="2"/>
</testsuite>
</testsuites> phpunit --log-junit <?xml version="1.0" encoding="UTF-8"?>
<testsuites name="PHPUnit tests">
<testsuite name="App\Tests\Unit\MeasurementValues\Infrastructure\Queue\Task\MeasurementArchivingTaskTest" file="/app/tests/Unit/MeasurementValues/Infrastructure/Queue/Task/MeasurementArchivingTaskTest.php" tests="1" assertions="2" errors="0" failures="0" skipped="0" time="0.018385">
<testcase name="testCallMethodToGenerateFile" file="/app/tests/Unit/MeasurementValues/Infrastructure/Queue/Task/MeasurementArchivingTaskTest.php" line="16" class="App\Tests\Unit\MeasurementValues\Infrastructure\Queue\Task\MeasurementArchivingTaskTest" classname="App.Tests.Unit.MeasurementValues.Infrastructure.Queue.Task.MeasurementArchivingTaskTest" assertions="2" time="0.018385"/>
</testsuite>
</testsuites> |
Dear @eerison |
Hey @kilatib in your script you have this like to copy from container to host docker cp -a "$container:$outputPath" "$outputPath" | - &>/dev/null I changed to this docker cp -a "$container:/app/tests/_output/phpunit-report.xml" "$outputPath" | - &>/dev/null shouldn't it be enough? copy |
Yes, I think so |
I would like to migrate from
vim-test
but it seems I'm missing something.My development environment is running inside Docker, so the way to execute the tests is:
but if I configure the
phpunit_cmd
like thisI'm getting this error
I also tried to substitute
$(docker ps -n=-1 -q --filter name=phpfpm --format="{{.ID}}")
with the real ID with no luck.And also I tried to through a shell script and got high CPU usage without a running test (and without any errors)
So how do I execute tests inside Docker?
The text was updated successfully, but these errors were encountered: