Refactor test suite

This commit is contained in:
Chris Tsang 2021-10-15 15:13:42 +08:00
parent 760c16a6a9
commit 668fb64224
19 changed files with 172 additions and 131 deletions

View File

@ -1,21 +1,17 @@
pub mod applog;
pub mod baker;
pub mod bakery;
pub mod cake;
pub mod cakes_bakers;
pub mod customer;
pub mod lineitem;
pub mod metadata;
pub mod order;
pub mod repository;
pub mod schema;
pub use super::applog::Entity as Applog;
pub use super::baker::Entity as Baker;
pub use super::bakery::Entity as Bakery;
pub use super::cake::Entity as Cake;
pub use super::cakes_bakers::Entity as CakesBakers;
pub use super::customer::Entity as Customer;
pub use super::lineitem::Entity as Lineitem;
pub use super::metadata::Entity as Metadata;
pub use super::order::Entity as Order;
pub use super::repository::Entity as Repository;
pub use baker::Entity as Baker;
pub use bakery::Entity as Bakery;
pub use cake::Entity as Cake;
pub use cakes_bakers::Entity as CakesBakers;
pub use customer::Entity as Customer;
pub use lineitem::Entity as Lineitem;
pub use order::Entity as Order;
pub use schema::*;

View File

@ -1,37 +1,18 @@
pub use super::super::bakery_chain::*;
use pretty_assertions::assert_eq;
use sea_orm::{
error::*, sea_query, ConnectionTrait, DbBackend, DbConn, EntityTrait, ExecResult, Schema,
};
use sea_query::{
Alias, ColumnDef, ForeignKey, ForeignKeyAction, Index, Table, TableCreateStatement,
};
use super::*;
use crate::common::setup::create_table;
use sea_orm::{error::*, sea_query, DatabaseConnection, DbConn, ExecResult};
use sea_query::{ColumnDef, ForeignKey, ForeignKeyAction, Index, Table};
async fn create_table<E>(
db: &DbConn,
create: &TableCreateStatement,
entity: E,
) -> Result<ExecResult, DbErr>
where
E: EntityTrait,
{
let builder = db.get_database_backend();
if builder != DbBackend::Sqlite {
let stmt = builder.build(
Table::drop()
.table(Alias::new(create.get_table_name().unwrap().as_ref()))
.if_exists()
.cascade(),
);
db.execute(stmt).await?;
}
pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> {
create_bakery_table(db).await?;
create_baker_table(db).await?;
create_customer_table(db).await?;
create_order_table(db).await?;
create_cake_table(db).await?;
create_cakes_bakers_table(db).await?;
create_lineitem_table(db).await?;
let stmt = builder.build(create);
assert_eq!(
builder.build(&Schema::create_table_from_entity(entity)),
stmt
);
db.execute(stmt).await
Ok(())
}
pub async fn create_bakery_table(db: &DbConn) -> Result<ExecResult, DbErr> {
@ -275,66 +256,3 @@ pub async fn create_cake_table(db: &DbConn) -> Result<ExecResult, DbErr> {
create_table(db, &stmt, Cake).await
}
pub async fn create_metadata_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(metadata::Entity)
.col(
ColumnDef::new(metadata::Column::Uuid)
.uuid()
.not_null()
.primary_key(),
)
.col(ColumnDef::new(metadata::Column::Type).string().not_null())
.col(ColumnDef::new(metadata::Column::Key).string().not_null())
.col(ColumnDef::new(metadata::Column::Value).string().not_null())
.col(ColumnDef::new(metadata::Column::Bytes).binary().not_null())
.col(ColumnDef::new(metadata::Column::Date).date())
.col(ColumnDef::new(metadata::Column::Time).time())
.to_owned();
create_table(db, &stmt, Metadata).await
}
pub async fn create_log_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(applog::Entity)
.col(
ColumnDef::new(applog::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(applog::Column::Action).string().not_null())
.col(ColumnDef::new(applog::Column::Json).json().not_null())
.col(
ColumnDef::new(applog::Column::CreatedAt)
.timestamp_with_time_zone()
.not_null(),
)
.to_owned();
create_table(db, &stmt, Applog).await
}
pub async fn create_repository_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(repository::Entity)
.col(
ColumnDef::new(repository::Column::Id)
.string()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(repository::Column::Owner)
.string()
.not_null(),
)
.col(ColumnDef::new(repository::Column::Name).string().not_null())
.col(ColumnDef::new(repository::Column::Description).string())
.to_owned();
create_table(db, &stmt, Repository).await
}

View File

@ -0,0 +1,9 @@
pub mod applog;
pub mod metadata;
pub mod repository;
pub mod schema;
pub use applog::Entity as Applog;
pub use metadata::Entity as Metadata;
pub use repository::Entity as Repository;
pub use schema::*;

View File

@ -0,0 +1,77 @@
pub use super::super::bakery_chain::*;
use super::*;
use crate::common::setup::create_table;
use sea_orm::{error::*, sea_query, DatabaseConnection, DbConn, ExecResult};
use sea_query::ColumnDef;
pub async fn create_tables(db: &DatabaseConnection) -> Result<(), DbErr> {
create_log_table(db).await?;
create_metadata_table(db).await?;
create_repository_table(db).await?;
Ok(())
}
pub async fn create_log_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(applog::Entity)
.col(
ColumnDef::new(applog::Column::Id)
.integer()
.not_null()
.auto_increment()
.primary_key(),
)
.col(ColumnDef::new(applog::Column::Action).string().not_null())
.col(ColumnDef::new(applog::Column::Json).json().not_null())
.col(
ColumnDef::new(applog::Column::CreatedAt)
.timestamp_with_time_zone()
.not_null(),
)
.to_owned();
create_table(db, &stmt, Applog).await
}
pub async fn create_metadata_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(metadata::Entity)
.col(
ColumnDef::new(metadata::Column::Uuid)
.uuid()
.not_null()
.primary_key(),
)
.col(ColumnDef::new(metadata::Column::Type).string().not_null())
.col(ColumnDef::new(metadata::Column::Key).string().not_null())
.col(ColumnDef::new(metadata::Column::Value).string().not_null())
.col(ColumnDef::new(metadata::Column::Bytes).binary().not_null())
.col(ColumnDef::new(metadata::Column::Date).date())
.col(ColumnDef::new(metadata::Column::Time).time())
.to_owned();
create_table(db, &stmt, Metadata).await
}
pub async fn create_repository_table(db: &DbConn) -> Result<ExecResult, DbErr> {
let stmt = sea_query::Table::create()
.table(repository::Entity)
.col(
ColumnDef::new(repository::Column::Id)
.string()
.not_null()
.primary_key(),
)
.col(
ColumnDef::new(repository::Column::Owner)
.string()
.not_null(),
)
.col(ColumnDef::new(repository::Column::Name).string().not_null())
.col(ColumnDef::new(repository::Column::Description).string())
.to_owned();
create_table(db, &stmt, Repository).await
}

View File

@ -1,10 +1,9 @@
pub mod bakery_chain;
pub mod features;
pub mod runtime;
pub mod setup;
pub use bakery_chain::*;
use sea_orm::DatabaseConnection;
use std::env;
pub struct TestContext {
base_url: String,
@ -15,7 +14,7 @@ pub struct TestContext {
impl TestContext {
pub async fn new(test_name: &str) -> Self {
let base_url =
env::var("DATABASE_URL").expect("Enviroment variable 'DATABASE_URL' not set");
std::env::var("DATABASE_URL").expect("Enviroment variable 'DATABASE_URL' not set");
let db: DatabaseConnection = setup::setup(&base_url, test_name).await;
Self {

View File

@ -1,6 +1,9 @@
use sea_orm::{ConnectionTrait, Database, DatabaseBackend, DatabaseConnection, Statement};
pub mod schema;
pub use schema::*;
use sea_orm::{
ConnectionTrait, Database, DatabaseBackend, DatabaseConnection, DbBackend, DbConn, DbErr,
EntityTrait, ExecResult, Schema, Statement,
};
use sea_query::{Alias, Table, TableCreateStatement};
pub async fn setup(base_url: &str, db_name: &str) -> DatabaseConnection {
let db = if cfg!(feature = "sqlx-mysql") {
@ -45,16 +48,6 @@ pub async fn setup(base_url: &str, db_name: &str) -> DatabaseConnection {
Database::connect(base_url).await.unwrap()
};
schema::create_bakery_table(&db).await.unwrap();
schema::create_baker_table(&db).await.unwrap();
schema::create_customer_table(&db).await.unwrap();
schema::create_order_table(&db).await.unwrap();
schema::create_cake_table(&db).await.unwrap();
schema::create_cakes_bakers_table(&db).await.unwrap();
schema::create_lineitem_table(&db).await.unwrap();
schema::create_metadata_table(&db).await.unwrap();
schema::create_log_table(&db).await.unwrap();
schema::create_repository_table(&db).await.unwrap();
db
}
@ -80,3 +73,30 @@ pub async fn tear_down(base_url: &str, db_name: &str) {
} else {
};
}
pub async fn create_table<E>(
db: &DbConn,
create: &TableCreateStatement,
entity: E,
) -> Result<ExecResult, DbErr>
where
E: EntityTrait,
{
let builder = db.get_database_backend();
if builder != DbBackend::Sqlite {
let stmt = builder.build(
Table::drop()
.table(Alias::new(create.get_table_name().unwrap().as_ref()))
.if_exists()
.cascade(),
);
db.execute(stmt).await?;
}
let stmt = builder.build(create);
assert_eq!(
builder.build(&Schema::create_table_from_entity(entity)),
stmt
);
db.execute(stmt).await
}

View File

@ -17,6 +17,7 @@ use sea_orm::DatabaseConnection;
))]
async fn main() {
let ctx = TestContext::new("bakery_chain_schema_crud_tests").await;
create_tables(&ctx.db).await;
create_entities(&ctx.db).await;
ctx.delete().await;
}

View File

@ -1,6 +1,6 @@
pub mod common;
pub use common::{bakery_chain::*, setup::*, TestContext};
pub use common::{features::*, setup::*, TestContext};
use pretty_assertions::assert_eq;
use sea_orm::{entity::prelude::*, DatabaseConnection, IntoActiveModel, Set};
@ -11,7 +11,8 @@ use sea_orm::{entity::prelude::*, DatabaseConnection, IntoActiveModel, Set};
feature = "sqlx-postgres"
))]
async fn main() -> Result<(), DbErr> {
let ctx = TestContext::new("bakery_chain_parallel_tests").await;
let ctx = TestContext::new("features_parallel_tests").await;
create_tables(&ctx.db).await;
crud_in_parallel(&ctx.db).await?;
ctx.delete().await;

View File

@ -14,6 +14,7 @@ pub use sea_orm::{ConnectionTrait, QueryFilter};
))]
pub async fn find_one_with_no_result() {
let ctx = TestContext::new("find_one_with_no_result").await;
create_tables(&ctx.db).await;
let bakery = Bakery::find().one(&ctx.db).await.unwrap();
assert_eq!(bakery, None);
@ -29,6 +30,7 @@ pub async fn find_one_with_no_result() {
))]
pub async fn find_one_with_result() {
let ctx = TestContext::new("find_one_with_result").await;
create_tables(&ctx.db).await;
let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
@ -54,6 +56,7 @@ pub async fn find_one_with_result() {
))]
pub async fn find_by_id_with_no_result() {
let ctx = TestContext::new("find_by_id_with_no_result").await;
create_tables(&ctx.db).await;
let bakery = Bakery::find_by_id(999).one(&ctx.db).await.unwrap();
assert_eq!(bakery, None);
@ -69,6 +72,7 @@ pub async fn find_by_id_with_no_result() {
))]
pub async fn find_by_id_with_result() {
let ctx = TestContext::new("find_by_id_with_result").await;
create_tables(&ctx.db).await;
let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
@ -98,6 +102,7 @@ pub async fn find_by_id_with_result() {
))]
pub async fn find_all_with_no_result() {
let ctx = TestContext::new("find_all_with_no_result").await;
create_tables(&ctx.db).await;
let bakeries = Bakery::find().all(&ctx.db).await.unwrap();
assert_eq!(bakeries.len(), 0);
@ -113,6 +118,7 @@ pub async fn find_all_with_no_result() {
))]
pub async fn find_all_with_result() {
let ctx = TestContext::new("find_all_with_result").await;
create_tables(&ctx.db).await;
let _ = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
@ -147,6 +153,7 @@ pub async fn find_all_with_result() {
))]
pub async fn find_all_filter_no_result() {
let ctx = TestContext::new("find_all_filter_no_result").await;
create_tables(&ctx.db).await;
let _ = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
@ -185,6 +192,7 @@ pub async fn find_all_filter_no_result() {
))]
pub async fn find_all_filter_with_results() {
let ctx = TestContext::new("find_all_filter_with_results").await;
create_tables(&ctx.db).await;
let _ = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),

View File

@ -17,6 +17,7 @@ pub use uuid::Uuid;
))]
pub async fn left_join() {
let ctx = TestContext::new("test_left_join").await;
create_tables(&ctx.db).await;
let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
@ -94,6 +95,7 @@ pub async fn left_join() {
#[cfg(any(feature = "sqlx-mysql", feature = "sqlx-postgres"))]
pub async fn right_join() {
let ctx = TestContext::new("test_right_join").await;
create_tables(&ctx.db).await;
let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
@ -179,6 +181,7 @@ pub async fn right_join() {
))]
pub async fn inner_join() {
let ctx = TestContext::new("test_inner_join").await;
create_tables(&ctx.db).await;
let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
@ -268,6 +271,7 @@ pub async fn inner_join() {
))]
pub async fn group_by() {
let ctx = TestContext::new("test_group_by").await;
create_tables(&ctx.db).await;
let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
@ -373,6 +377,7 @@ pub async fn group_by() {
pub async fn having() {
// customers with orders with total equal to $90
let ctx = TestContext::new("test_having").await;
create_tables(&ctx.db).await;
let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
@ -487,6 +492,7 @@ pub async fn linked() -> Result<(), DbErr> {
use sea_orm::{SelectA, SelectB};
let ctx = TestContext::new("test_linked").await;
create_tables(&ctx.db).await;
// SeaSide Bakery
let seaside_bakery = bakery::ActiveModel {

View File

@ -14,6 +14,7 @@ pub use uuid::Uuid;
pub async fn test_multiple_operations() {
let ctx = TestContext::new("multiple_sequential_operations").await;
create_tables(&ctx.db).await;
init_setup(&ctx.db).await;
let baker_least_sales = find_baker_least_sales(&ctx.db).await.unwrap();
assert_eq!(baker_least_sales.name, "Baker 2");

View File

@ -14,6 +14,7 @@ pub async fn stream() -> Result<(), DbErr> {
use futures::StreamExt;
let ctx = TestContext::new("stream").await;
create_tables(&ctx.db).await;
let bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),

View File

@ -1,6 +1,6 @@
pub mod common;
pub use common::{bakery_chain::*, setup::*, TestContext};
pub use common::{features::*, setup::*, TestContext};
use pretty_assertions::assert_eq;
use sea_orm::{entity::prelude::*, entity::*, DatabaseConnection};
@ -11,7 +11,8 @@ use sea_orm::{entity::prelude::*, entity::*, DatabaseConnection};
feature = "sqlx-postgres"
))]
async fn main() -> Result<(), DbErr> {
let ctx = TestContext::new("bakery_chain_schema_string_primary_key_tests").await;
let ctx = TestContext::new("features_schema_string_primary_key_tests").await;
create_tables(&ctx.db).await;
create_and_update_repository(&ctx.db).await?;
insert_repository(&ctx.db).await?;
ctx.delete().await;

View File

@ -1,12 +1,13 @@
pub mod common;
pub use common::{bakery_chain::*, setup::*, TestContext};
pub use common::{features::*, setup::*, TestContext};
use sea_orm::{entity::prelude::*, DatabaseConnection, IntoActiveModel};
#[sea_orm_macros::test]
#[cfg(feature = "sqlx-postgres")]
async fn main() -> Result<(), DbErr> {
let ctx = TestContext::new("bakery_chain_schema_timestamp_tests").await;
create_tables(&ctx.db).await;
create_applog(&ctx.db).await?;
ctx.delete().await;

View File

@ -1,6 +1,6 @@
pub mod common;
pub use common::{bakery_chain::*, setup::*, TestContext};
pub use common::{features::*, setup::*, TestContext};
pub use sea_orm::entity::*;
pub use sea_orm::{ConnectionTrait, QueryFilter};
use sea_orm::{DatabaseTransaction, DbErr};
@ -13,6 +13,7 @@ use sea_orm::{DatabaseTransaction, DbErr};
))]
pub async fn transaction() {
let ctx = TestContext::new("transaction_test").await;
create_tables(&ctx.db).await;
ctx.db
.transaction::<_, _, DbErr>(|txn| {

View File

@ -1,6 +1,6 @@
pub mod common;
pub use common::{bakery_chain::*, setup::*, TestContext};
pub use common::{features::*, setup::*, TestContext};
use sea_orm::{entity::prelude::*, entity::*, DatabaseConnection};
#[sea_orm_macros::test]
@ -11,6 +11,7 @@ use sea_orm::{entity::prelude::*, entity::*, DatabaseConnection};
))]
async fn main() -> Result<(), DbErr> {
let ctx = TestContext::new("bakery_chain_schema_uuid_tests").await;
create_tables(&ctx.db).await;
create_and_update_metadata(&ctx.db).await?;
insert_metadata(&ctx.db).await?;
ctx.delete().await;