Skip to content

Commit 688a88e

Browse files
committed
Add a --test-db global parameter to diesel_cli that switches to TEST_DATABASE_URL env instead of DATABASE_URL env
1 parent 2307f29 commit 688a88e

File tree

4 files changed

+197
-36
lines changed

4 files changed

+197
-36
lines changed

diesel_cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ path = "../diesel_migrations/"
6868

6969
[dev-dependencies]
7070
tempfile = "3.1.0"
71+
temp-env = "0.3"
7172
regex = "1.3.9"
7273
insta = "1.21"
7374

diesel_cli/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ ways that you can set it:
7070
* Set it as an environment variable using [dotenv](https://github.com/dotenv-rs/dotenv#examples)
7171
* Pass it directly by adding the `--database-url` flag
7272

73+
To support a test database during development, passing --test-db to have
74+
diesel load the database url from TEST_DATABASE_URL instead.
75+
7376
As an alternative to running migrations with the CLI, you can call
7477
[`diesel::migrations::run_pending_migrations`][pending-migrations] from
7578
`build.rs`.

diesel_cli/src/cli.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,16 @@ pub fn build_cli() -> Command {
356356
.global(true)
357357
.num_args(1);
358358

359+
let test_db_arg = Arg::new("TEST_DB")
360+
.long("test-db")
361+
.short('t')
362+
.help(
363+
"Enable using a test db. This switches the database-url fall back to load from the \
364+
TEST_DATABASE_URL environment variable before DATABASE_URL.",
365+
)
366+
.global(true)
367+
.action(ArgAction::SetTrue);
368+
359369
let locked_schema_arg = Arg::new("LOCKED_SCHEMA")
360370
.long("locked-schema")
361371
.help("Require that the schema file is up to date.")
@@ -384,6 +394,7 @@ pub fn build_cli() -> Command {
384394
)
385395
.arg(database_arg)
386396
.arg(config_arg)
397+
.arg(test_db_arg)
387398
.arg(locked_schema_arg)
388399
.subcommand(migration_subcommand)
389400
.subcommand(setup_subcommand)

diesel_cli/src/database.rs

Lines changed: 182 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,14 @@ pub fn database_url(matches: &ArgMatches) -> Result<String, crate::errors::Error
413413
matches
414414
.get_one::<String>("DATABASE_URL")
415415
.cloned()
416-
.or_else(|| env::var("DATABASE_URL").ok())
416+
.or_else(|| {
417+
let is_test_db = matches.get_one::<bool>("TEST_DB").cloned().unwrap_or(false);
418+
if is_test_db {
419+
env::var("TEST_DATABASE_URL").ok()
420+
} else {
421+
env::var("DATABASE_URL").ok()
422+
}
423+
})
417424
.ok_or(crate::errors::Error::DatabaseUrlMissing)
418425
}
419426

@@ -469,44 +476,183 @@ fn path_from_sqlite_url(database_url: &str) -> Result<std::path::PathBuf, crate:
469476
}
470477
}
471478

472-
#[cfg(all(test, any(feature = "postgres", feature = "mysql")))]
479+
#[cfg(test)]
473480
mod tests {
474-
use super::change_database_of_url;
475-
476-
#[test]
477-
fn split_pg_connection_string_returns_postgres_url_and_database() {
478-
let database = "database".to_owned();
479-
let base_url = "postgresql://localhost:5432".to_owned();
480-
let database_url = format!("{base_url}/{database}");
481-
let postgres_url = format!("{}/{}", base_url, "postgres");
482-
assert_eq!(
483-
(database, postgres_url),
484-
change_database_of_url(&database_url, "postgres").unwrap()
485-
);
486-
}
481+
mod database_url {
482+
use super::super::database_url;
483+
use crate::cli::build_cli;
484+
485+
#[test]
486+
fn when_no_database_url_arg_returns_database_url_env() {
487+
let cli = build_cli();
488+
temp_env::with_vars(
489+
[
490+
("DATABASE_URL", Some("sqlite:///prod.sqlite")),
491+
("TEST_DATABASE_URL", Some("sqlite:///test.sqlite")),
492+
],
493+
|| {
494+
let matches = cli
495+
.clone()
496+
.try_get_matches_from(["diesel", "setup"])
497+
.unwrap();
498+
let ret = database_url(&matches);
499+
assert!(ret.is_ok());
500+
assert_eq!(ret.unwrap(), "sqlite:///prod.sqlite");
501+
},
502+
);
503+
}
504+
505+
#[test]
506+
fn when_no_database_url_arg_nor_env_returns_error() {
507+
let cli = build_cli();
508+
temp_env::with_vars(
509+
[
510+
("DATABASE_URL", None::<&str>),
511+
("TEST_DATABASE_URL", None::<&str>),
512+
],
513+
|| {
514+
let matches = cli
515+
.clone()
516+
.try_get_matches_from(["diesel", "setup"])
517+
.unwrap();
518+
let ret = database_url(&matches);
519+
assert!(ret.is_err());
520+
assert!(matches!(
521+
ret.unwrap_err(),
522+
crate::errors::Error::DatabaseUrlMissing
523+
));
524+
},
525+
);
526+
}
527+
528+
#[test]
529+
fn when_database_url_arg_returns_database_url_arg() {
530+
let cli = build_cli();
531+
temp_env::with_vars(
532+
[
533+
("DATABASE_URL", Some("sqlite:///prod.sqlite")),
534+
("TEST_DATABASE_URL", Some("sqlite:///test.sqlite")),
535+
],
536+
|| {
537+
let matches = cli
538+
.clone()
539+
.try_get_matches_from([
540+
"diesel",
541+
"setup",
542+
"--database-url",
543+
"sqlite:///arg.sqlite",
544+
])
545+
.unwrap();
546+
let ret = database_url(&matches);
547+
assert!(ret.is_ok());
548+
assert_eq!(ret.unwrap(), "sqlite:///arg.sqlite");
549+
},
550+
);
551+
}
552+
553+
#[test]
554+
fn when_test_db_and_no_database_url_arg_returns_test_database_url_env() {
555+
let cli = build_cli();
556+
temp_env::with_vars(
557+
[
558+
("DATABASE_URL", Some("sqlite:///prod.sqlite")),
559+
("TEST_DATABASE_URL", Some("sqlite:///test.sqlite")),
560+
],
561+
|| {
562+
let matches = cli
563+
.clone()
564+
.try_get_matches_from(["diesel", "setup", "--test-db"])
565+
.unwrap();
566+
let ret = database_url(&matches);
567+
assert!(ret.is_ok());
568+
assert_eq!(ret.unwrap(), "sqlite:///test.sqlite");
569+
},
570+
);
571+
}
487572

488-
#[test]
489-
fn split_pg_connection_string_handles_user_and_password() {
490-
let database = "database".to_owned();
491-
let base_url = "postgresql://user:password@localhost:5432".to_owned();
492-
let database_url = format!("{base_url}/{database}");
493-
let postgres_url = format!("{}/{}", base_url, "postgres");
494-
assert_eq!(
495-
(database, postgres_url),
496-
change_database_of_url(&database_url, "postgres").unwrap()
497-
);
573+
#[test]
574+
fn when_test_db_and_no_test_url_env_returns_error() {
575+
let cli = build_cli();
576+
temp_env::with_vars([("DATABASE_URL", Some("sqlite:///prod.sqlite"))], || {
577+
let matches = cli
578+
.clone()
579+
.try_get_matches_from(["diesel", "setup", "--test-db"])
580+
.unwrap();
581+
let ret = database_url(&matches);
582+
assert!(ret.is_err());
583+
assert!(matches!(
584+
ret.unwrap_err(),
585+
crate::errors::Error::DatabaseUrlMissing
586+
));
587+
});
588+
}
589+
590+
#[test]
591+
fn when_test_db_and_database_url_arg_returns_database_url_arg() {
592+
let cli = build_cli();
593+
temp_env::with_vars(
594+
[
595+
("DATABASE_URL", Some("sqlite:///prod.sqlite")),
596+
("TEST_DATABASE_URL", Some("sqlite:///test.sqlite")),
597+
],
598+
|| {
599+
let matches = cli
600+
.clone()
601+
.try_get_matches_from([
602+
"diesel",
603+
"setup",
604+
"--test-db",
605+
"--database-url",
606+
"sqlite:///arg.sqlite",
607+
])
608+
.unwrap();
609+
let ret = database_url(&matches);
610+
assert!(ret.is_ok());
611+
assert_eq!(ret.unwrap(), "sqlite:///arg.sqlite");
612+
},
613+
);
614+
}
498615
}
499616

500-
#[test]
501-
fn split_pg_connection_string_handles_query_string() {
502-
let database = "database".to_owned();
503-
let query = "?sslmode=true".to_owned();
504-
let base_url = "postgresql://user:password@localhost:5432".to_owned();
505-
let database_url = format!("{base_url}/{database}{query}");
506-
let postgres_url = format!("{}/{}{}", base_url, "postgres", query);
507-
assert_eq!(
508-
(database, postgres_url),
509-
change_database_of_url(&database_url, "postgres").unwrap()
510-
);
617+
#[cfg(any(feature = "postgres", feature = "mysql"))]
618+
mod change_of_url_tests {
619+
use super::super::change_database_of_url;
620+
621+
#[test]
622+
fn split_pg_connection_string_returns_postgres_url_and_database() {
623+
let database = "database".to_owned();
624+
let base_url = "postgresql://localhost:5432".to_owned();
625+
let database_url = format!("{base_url}/{database}");
626+
let postgres_url = format!("{}/{}", base_url, "postgres");
627+
assert_eq!(
628+
(database, postgres_url),
629+
change_database_of_url(&database_url, "postgres").unwrap()
630+
);
631+
}
632+
633+
#[test]
634+
fn split_pg_connection_string_handles_user_and_password() {
635+
let database = "database".to_owned();
636+
let base_url = "postgresql://user:password@localhost:5432".to_owned();
637+
let database_url = format!("{base_url}/{database}");
638+
let postgres_url = format!("{}/{}", base_url, "postgres");
639+
assert_eq!(
640+
(database, postgres_url),
641+
change_database_of_url(&database_url, "postgres").unwrap()
642+
);
643+
}
644+
645+
#[test]
646+
fn split_pg_connection_string_handles_query_string() {
647+
let database = "database".to_owned();
648+
let query = "?sslmode=true".to_owned();
649+
let base_url = "postgresql://user:password@localhost:5432".to_owned();
650+
let database_url = format!("{base_url}/{database}{query}");
651+
let postgres_url = format!("{}/{}{}", base_url, "postgres", query);
652+
assert_eq!(
653+
(database, postgres_url),
654+
change_database_of_url(&database_url, "postgres").unwrap()
655+
);
656+
}
511657
}
512658
}

0 commit comments

Comments
 (0)