.. | ||
fixtures | ||
migration-test | ||
schemas | ||
actions_commit_status_test.go | ||
actions_job_test.go | ||
actions_log_test.go | ||
actions_route_test.go | ||
actions_runner_test.go | ||
actions_trigger_test.go | ||
admin_config_test.go | ||
admin_user_test.go | ||
api_actions_artifact_test.go | ||
api_actions_artifact_v4_test.go | ||
api_activitypub_actor_test.go | ||
api_activitypub_person_test.go | ||
api_activitypub_repository_test.go | ||
api_admin_actions_test.go | ||
api_admin_org_test.go | ||
api_admin_test.go | ||
api_block_test.go | ||
api_branch_test.go | ||
api_comment_attachment_test.go | ||
api_comment_test.go | ||
api_feed_plain_text_titles_test.go | ||
api_feed_user_test.go | ||
api_forgejo_root_test.go | ||
api_forgejo_version_test.go | ||
api_fork_test.go | ||
api_gitignore_templates_test.go | ||
api_gpg_keys_test.go | ||
api_health_test.go | ||
api_helper_for_declarative_test.go | ||
api_httpsig_test.go | ||
api_issue_attachment_test.go | ||
api_issue_config_test.go | ||
api_issue_label_test.go | ||
api_issue_milestone_test.go | ||
api_issue_pin_test.go | ||
api_issue_reaction_test.go | ||
api_issue_stopwatch_test.go | ||
api_issue_subscription_test.go | ||
api_issue_templates_test.go | ||
api_issue_test.go | ||
api_issue_tracked_time_test.go | ||
api_keys_test.go | ||
api_label_templates_test.go | ||
api_license_templates_test.go | ||
api_nodeinfo_test.go | ||
api_notification_test.go | ||
api_oauth2_apps_test.go | ||
api_org_actions_test.go | ||
api_org_avatar_test.go | ||
api_org_test.go | ||
api_packages_alpine_test.go | ||
api_packages_alt_test.go | ||
api_packages_arch_test.go | ||
api_packages_cargo_test.go | ||
api_packages_chef_test.go | ||
api_packages_composer_test.go | ||
api_packages_conan_test.go | ||
api_packages_conda_test.go | ||
api_packages_container_cleanup_sha256_test.go | ||
api_packages_container_test.go | ||
api_packages_cran_test.go | ||
api_packages_debian_test.go | ||
api_packages_generic_test.go | ||
api_packages_goproxy_test.go | ||
api_packages_helm_test.go | ||
api_packages_maven_test.go | ||
api_packages_npm_test.go | ||
api_packages_nuget_test.go | ||
api_packages_pub_test.go | ||
api_packages_pypi_test.go | ||
api_packages_rpm_test.go | ||
api_packages_rubygems_test.go | ||
api_packages_swift_test.go | ||
api_packages_test.go | ||
api_packages_vagrant_test.go | ||
api_private_serv_test.go | ||
api_pull_commits_test.go | ||
api_pull_review_test.go | ||
api_pull_test.go | ||
api_push_mirror_test.go | ||
api_quota_management_test.go | ||
api_quota_use_test.go | ||
api_releases_test.go | ||
api_repo_actions_test.go | ||
api_repo_activities_test.go | ||
api_repo_archive_test.go | ||
api_repo_avatar_test.go | ||
api_repo_branch_test.go | ||
api_repo_collaborator_test.go | ||
api_repo_compare_test.go | ||
api_repo_edit_test.go | ||
api_repo_file_create_test.go | ||
api_repo_file_delete_test.go | ||
api_repo_file_get_test.go | ||
api_repo_file_helpers.go | ||
api_repo_file_update_test.go | ||
api_repo_files_change_test.go | ||
api_repo_get_contents_list_test.go | ||
api_repo_get_contents_test.go | ||
api_repo_git_blobs_test.go | ||
api_repo_git_commits_test.go | ||
api_repo_git_hook_test.go | ||
api_repo_git_notes_test.go | ||
api_repo_git_ref_test.go | ||
api_repo_git_tags_test.go | ||
api_repo_git_trees_test.go | ||
api_repo_hook_test.go | ||
api_repo_languages_test.go | ||
api_repo_lfs_locks_test.go | ||
api_repo_lfs_migrate_test.go | ||
api_repo_lfs_test.go | ||
api_repo_raw_test.go | ||
api_repo_secrets_test.go | ||
api_repo_tags_test.go | ||
api_repo_teams_test.go | ||
api_repo_test.go | ||
api_repo_topic_test.go | ||
api_repo_variables_test.go | ||
api_settings_test.go | ||
api_team_test.go | ||
api_team_user_test.go | ||
api_token_test.go | ||
api_twofa_test.go | ||
api_user_actions_test.go | ||
api_user_avatar_test.go | ||
api_user_email_test.go | ||
api_user_follow_test.go | ||
api_user_heatmap_test.go | ||
api_user_info_test.go | ||
api_user_org_perm_test.go | ||
api_user_orgs_test.go | ||
api_user_search_test.go | ||
api_user_secrets_test.go | ||
api_user_star_test.go | ||
api_user_variables_test.go | ||
api_user_watch_test.go | ||
api_wiki_test.go | ||
archived_labels_display_test.go | ||
attachment_test.go | ||
auth_ldap_test.go | ||
auth_token_test.go | ||
avatar.png | ||
benchmarks_test.go | ||
block_test.go | ||
branches_test.go | ||
change_default_branch_test.go | ||
cmd_admin_test.go | ||
cmd_forgejo_actions_test.go | ||
cmd_forgejo_f3_test.go | ||
cmd_keys_test.go | ||
codeowner_test.go | ||
commit_status_test.go | ||
compare_test.go | ||
cors_test.go | ||
create_no_session_test.go | ||
csrf_test.go | ||
db_collation_test.go | ||
delete_user_test.go | ||
doctor_packages_nuget_test.go | ||
download_test.go | ||
dummy_lang_test.go | ||
dump_restore_test.go | ||
easymde_test.go | ||
editor_test.go | ||
empty_repo_test.go | ||
eventsource_test.go | ||
explore_code_test.go | ||
explore_org_test.go | ||
explore_repos_test.go | ||
explore_user_test.go | ||
forgejo_confirmation_repo_test.go | ||
forgejo_git_test.go | ||
git_helper_for_declarative_test.go | ||
git_push_test.go | ||
git_smart_http_test.go | ||
git_test.go | ||
goget_test.go | ||
gpg_git_test.go | ||
html_helper.go | ||
incoming_email_test.go | ||
integration_test.go | ||
issue_subscribe_test.go | ||
issue_test.go | ||
issues_comment_labels_test.go | ||
last_updated_time_test.go | ||
lfs_getobject_test.go | ||
lfs_local_endpoint_test.go | ||
lfs_view_test.go | ||
linguist_test.go | ||
links_test.go | ||
markup_external_test.go | ||
markup_test.go | ||
mention_test.go | ||
migrate_test.go | ||
milestone_test.go | ||
mirror_pull_test.go | ||
mirror_push_test.go | ||
new_org_test.go | ||
nonascii_branches_test.go | ||
notification_test.go | ||
oauth_test.go | ||
opengraph_test.go | ||
org_count_test.go | ||
org_nav_test.go | ||
org_project_test.go | ||
org_settings_test.go | ||
org_team_invite_test.go | ||
org_test.go | ||
private-testing.key | ||
privateactivity_test.go | ||
proctected_branch_test.go | ||
project_test.go | ||
pull_commit_test.go | ||
pull_compare_test.go | ||
pull_create_test.go | ||
pull_diff_test.go | ||
pull_icon_test.go | ||
pull_merge_test.go | ||
pull_reopen_test.go | ||
pull_request_task_test.go | ||
pull_review_test.go | ||
pull_status_test.go | ||
pull_summary_test.go | ||
pull_test.go | ||
pull_update_test.go | ||
pull_wip_convert_test.go | ||
quota_use_test.go | ||
README.md | ||
release_test.go | ||
remote_test.go | ||
rename_branch_test.go | ||
repo_activity_test.go | ||
repo_archive_test.go | ||
repo_archive_text_test.go | ||
repo_badges_test.go | ||
repo_branch_test.go | ||
repo_citation_test.go | ||
repo_collaborator_test.go | ||
repo_commits_search_test.go | ||
repo_commits_test.go | ||
repo_delete_test.go | ||
repo_flags_test.go | ||
repo_fork_test.go | ||
repo_generate_test.go | ||
repo_git_note_test.go | ||
repo_issue_title_test.go | ||
repo_mergecommit_revert_test.go | ||
repo_migrate_test.go | ||
repo_migration_ui_test.go | ||
repo_pagination_test.go | ||
repo_search_test.go | ||
repo_settings_hook_test.go | ||
repo_settings_test.go | ||
repo_signed_tag_test.go | ||
repo_starwatch_test.go | ||
repo_tag_test.go | ||
repo_test.go | ||
repo_topic_test.go | ||
repo_view_test.go | ||
repo_watch_test.go | ||
repo_webhook_test.go | ||
repo_wiki_test.go | ||
repofiles_change_test.go | ||
session_test.go | ||
setting_test.go | ||
signin_test.go | ||
signout_test.go | ||
signup_test.go | ||
size_translations_test.go | ||
ssh_key_test.go | ||
swagger_test.go | ||
timetracking_test.go | ||
user_avatar_test.go | ||
user_count_test.go | ||
user_dashboard_test.go | ||
user_profile_activity_test.go | ||
user_profile_follows_test.go | ||
user_profile_test.go | ||
user_redirect_test.go | ||
user_test.go | ||
version_test.go | ||
view_test.go | ||
webfinger_test.go | ||
webhook_test.go | ||
wiki_test.go | ||
xss_test.go |
Integration tests
Thank you for your effort to provide good software tests for Forgejo. Please also read the general testing instructions in the Forgejo contributor documentation.
This file is meant to provide specific information for the integration tests as well as some tips and tricks you should know.
Feel free to extend this file with more instructions if you feel like you have something to share!
How to run the tests?
Before running any tests, please ensure you perform a clean build:
make clean build
Integration tests can be run with make commands for the appropriate backends, namely:
make test-sqlite
make test-pgsql
make test-mysql
Run tests via local forgejo runner
If you have a forgejo runner, you can use it to run the test jobs:
Run all jobs
forgejo-runner exec -W .forgejo/workflows/testing.yml --event=pull_request
Warning: This file defines many jobs, so it will be resource-intensive and therefore not recommended.
Run single job
forgejo-runner exec -W .forgejo/workflows/testing.yml --event=pull_request -j <job_name>
You can list all job names via:
forgejo-runner exec -W .forgejo/workflows/testing.yml --event=pull_request -l
Run sqlite integration tests
Start tests
make test-sqlite
Run MySQL integration tests
Setup a MySQL database inside docker
docker run -e MYSQL_DATABASE=test -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -p 3306:3306 --rm --name mysql mysql:latest #(Ctrl-c to stop the database)
Start tests based on the database container
TEST_MYSQL_HOST=localhost:3306 TEST_MYSQL_DBNAME=test?multiStatements=true TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-mysql
Run pgsql integration tests
Setup a pgsql database inside docker
docker run -e "POSTGRES_DB=test" -e POSTGRES_PASSWORD=postgres -p 5432:5432 --rm --name pgsql postgres:latest #(Ctrl-c to stop the database)
Start tests based on the database container
TEST_STORAGE_TYPE=local TEST_PGSQL_HOST=localhost:5432 TEST_PGSQL_DBNAME=test TEST_PGSQL_USERNAME=postgres TEST_PGSQL_PASSWORD=postgres make test-pgsql
Running individual tests
Example command to run GPG test:
For SQLite:
make test-sqlite#GPG
For other databases (replace mysql
to pgsql
):
TEST_MYSQL_HOST=localhost:1433 TEST_MYSQL_DBNAME=test TEST_MYSQL_USERNAME=sa TEST_MYSQL_PASSWORD=MwantsaSecurePassword1 make test-mysql#GPG
Setting timeouts for declaring long-tests and long-flushes
We appreciate that some testing machines may not be very powerful and the default timeouts for declaring a slow test or a slow clean-up flush may not be appropriate.
You can either:
- Within the test ini file set the following section:
[integration-tests]
SLOW_TEST = 10s ; 10s is the default value
SLOW_FLUSH = 5S ; 5s is the default value
- Set the following environment variables:
GITEA_SLOW_TEST_TIME="10s" GITEA_SLOW_FLUSH_TIME="5s" make test-sqlite
Tips and tricks
If you know noteworthy tests that can act as an inspiration for new tests, please add some details here.
Example: Test app.ini parameter with effect on visible elements
The test file and where to find it
The file is defined in:
forgejo/tests/integration/disable_forgotten_password_test.go
and the test function is called:
TestDisableForgottenPasswordTrue
How to run the isolated test
Now we know the name of the test function (well, we defined it). We can run a selected test function via:
make clean build
make test-sqlite#TestDisableForgottenPasswordTrue
The parameter we want to manipulate
The first line of interest is
defer test.MockVariableValue(&setting.Service.SignInForgottenPasswordEnabled, true)()
Here we set the app.ini parameter
[Service]
SIGNIN_FORGOTTEN_PASSWORD_ENABLED
to true.
As you can see, the test doesn't include the processing of the actual parameter of SIGNIN_FORGOTTEN_PASSWORD_ENABLED in the app.ini. We start your test after modules/setting/service.go processed it this:
Service.SignInForgottenPasswordEnabled = sec.Key("SIGNIN_FORGOTTEN_PASSWORD_ENABLED").MustBool(true)
In the case SignInForgottenPasswordEnabled doesn't exist in modules/setting/service.go (e.g. by misspelling it or if it just doesn't exists), you will get an error when running the test. i.e. the test will not run.
Get the page
Our parameter SIGNIN_FORGOTTEN_PASSWORD_ENABLED enables and disables the "Forgotten Password?" link on the /user/login page. Thus we want to inverstigate what happens at /user/login page and we need to grep that webpage:
req := NewRequest(t, "GET", "/user/login/")
resp := MakeRequest(t, req, http.StatusOK)
Note: You can add "fmt" to the import section and then use e.g.
fmt.Printf("XXXXX %+v\n",resp)
to "visually" inspect what is going on (here the variable resp). We add the tag XXXXX because this help to visually find the output as well as allow to search for it easily. Or %T to see the type of a variable:
parser := NewHTMLParser(t, resp.Body)
fmt.Printf("XXXXX %T\n",parser)
This tells us that the parser is related to integration.HTMLDoc. (we can google this "go integration.HTMLDoc" for more information)
Parse the page and find selectors
We find more information about integration.HTMLDoc here: https://pkg.go.dev/code.gitea.io/gitea/tests/integration
More specifically we are interested in .Find() https://pkg.go.dev/code.gitea.io/gitea/tests/integration#HTMLDoc.Find
After we looked into resp, we know that the target of our interest lies in the lines:
<div class="field">
<a href="/user/forgot_password">Forgot password?</a>
</div>
Hence we ask the parser to find all instances of a link:
doc := NewHTMLParser(t, resp.Body).Find("a")
Obviously, there will be more than one link on the page. Thus we will inspect them individually via a for loop:
for i := range doc.Nodes {
one_element := doc.Eq(i)
}
one_element is of "type Selection" ( more information how the methods type has see here: https://pkg.go.dev/github.com/PuerkitoBio/goquery#Selection )
For example we can list the value which is in between "" and "" with
doc := NewHTMLParser(t, resp.Body).Find("a")
for i := range doc.Nodes {
oneElement := doc.Eq(i)
htmlText, _ := oneElement.Html()
fmt.Printf("XXXXX %+v\n",htmlText)
}
For our problem we could now check for "Forgot password?" which is in between "" "". But this is theoretically depended on the language setting and also not the functionality we want to check against. Hence, we will focus on the link itself. We get the link information via the .Attr() method:
doc := NewHTMLParser(t, resp.Body).Find("a")
for i := range doc.Nodes {
oneElement := doc.Eq(i)
attValue, attExists := oneElement.Attr("href")
if attExists {
fmt.Printf("XXXXX %+v\n",attValue)
}
}
This results in:
XXXXX /
XXXXX /explore/repos
XXXXX https://forgejo.org/docs/latest/
XXXXX /user/sign_up
XXXXX /user/login
XXXXX /user/sign_up
XXXXX /user/forgot_password
XXXXX https://forgejo.org
XXXXX /assets/licenses.txt
XXXXX /api/swagger
Now we count the number of instances of "/user/forgot_password" and evaluate that.
package integration
import (
"net/http"
"testing"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
func TestDisableForgottenPasswordTrue(t *testing.T) {
defer tests.PrepareTestEnv(t)()
defer test.MockVariableValue(&setting.Service.SignInForgottenPasswordEnabled, true)()
req := NewRequest(t, "GET", "/user/login/")
resp := MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body).Find("a")
var counterInstances int = 0
for i := range doc.Nodes {
oneElement := doc.Eq(i)
attValue, attExists := oneElement.Attr("href")
if attExists {
if attValue == "/user/forgot_password" {
counterInstances += 1
}
}
}
assert.EqualValues(t, 1, counterInstances)
}
One is the loneliest number because it is the only correct solution here.
assert.EqualValues(t, 1, counterInstances)
Note: Other options for assert can be found here: https://pkg.go.dev/github.com/stretchr/testify/assert
Adding the two other cases
We make two copies of
func TestDisableForgottenPasswordTrue(t *testing.T)
and call them
func TestDisableForgottenPasswordDefault(t *testing.T)
and
func TestDisableForgottenPasswordFalse(t *testing.T)
In
func TestDisableForgottenPasswordDefault(t *testing.T)
we remove the line
defer test.MockVariableValue(&setting.Service.SignInForgottenPasswordEnabled, true)()
to test the default setting.
In
func TestDisableForgottenPasswordFalse(t *testing.T)
we change the two lines:
defer test.MockVariableValue(&setting.Service.SignInForgottenPasswordEnabled, false)()
(parameter is false) and
assert.EqualValues(t, 0, counterInstances)
(the link never occurs i.e. counterInstances is zero).
Final test
Check if everything works during the real test:
make test-sqlite
=== TestDisableForgottenPasswordTrue (tests/integration/disable_forgotten_password_test.go:15)
=== TestDisableForgottenPasswordDefault (tests/integration/disable_forgotten_password_test.go:35)
=== TestDisableForgottenPasswordFalse (tests/integration/disable_forgotten_password_test.go:54)