I'm automating UI tests to my Silverlight App and I'm using Visual Studio 2010 for it. Some tests required a setup to my Oracle Database.
Things i've done:
1 - A setup.sql file where I connect to my Database and perform actions on it. I had this file as an existing item to my project and I add as a Deployment on TestSettings.
Code:
CONNECT USERNAME#DATABASE,
CREATE TABLE TABLE_NAME,
EXIT
2 - A set.bat file where I call the setup.sql file. I had the path of this file on Setup and Cleanup tab on TestSetings.
Code:
sqlcmd -S MARIALISBOA -i setup.sql
3 - I wrote a TestInitilize method on my TestClass.
Code:
[TestInitialize()]
public void Initialize()
{
System.Diagnostics.Process.Start("setup.bat");
}
4 - I connected do my Database throw Visual Studio (Data -> Add New Data Source).
I run a test on Visual Studio but the class isn't created on my database.
Could anyone help me? I'm trying to solve this problem since Monday and I starting to lose my mind
While it does not solve your initial problem, a solution would be to use something similiar to this;
Do not create the table within your tests. this should be created on install of the Test Environment
Clear down the table for each test you want to do using a Helper Method within the test.
For example (Please note that this is SQL Server, use OLE DB connection or similiar);
internal static object FireSqlStatement(string sqlStatement)
{
object result = null;
using (var cn = new SqlConnection(ConfigurationManager.ConnectionStrings[connectionString].ConnectionString))
{
cn.Open();
var cmd = new SqlCommand
{
CommandText = sqlStatement,
CommandType = CommandType.Text,
Connection = cn
};
result = cmd.ExecuteScalar();
cmd.Dispose();
cn.Close();
}
return result;
}
An example of how I use this within my test;
[Test]
public void GetUserTriggers()
{
//Insert Test Record
Helper.FireSqlStatement("INSERT INTO [Users].[Triggers] (Id) VALUES (1)");
var request = new GetTriggersRequest()
{
TriggerType = TriggerType.UserTrigger
};
var response = ServiceInvoker.Invoke<IReports,
GetTriggersRequest, GetTriggersResponse>(
"Reports",
request,
(proxy, req) => proxy.GetTriggers(req));
foreach (var t in response.Triggers)
{
Console.WriteLine(t.Id.ToString());
}
Assert.NotNull(response);
Assert.NotNull(response.Triggers);
Assert.Greater(response.Triggers.Count, 0);
}
In your case, you could call;
Helper.FireSqlStatement("TRUNCATE TABLE tableName");
Any good?
Related
I've set up a Unit Test project in Visual studio for my SQL Server project.
The test itself work, and the setup includes deploying that database. My problem is that I want to have a "clean slate" test, and every time I run a test, the data accumulates.
I tried manually calling a 'DROP DATABASE' from the SqlDatabaseSetup.cs, but it seems that I don't have a DataConnection at this point.
[TestClass()]
public class SqlDatabaseSetup
{
[AssemblyInitialize()]
public static void InitializeAssembly(TestContext ctx)
{
var q = ctx.DataConnection.CreateCommand();
q.CommandText = "DROP DATABASE MyDb;";
q.ExecuteNonQuery();
// Setup the test database based on setting in the
// configuration file
SqlDatabaseTestClass.TestService.DeployDatabaseProject();
SqlDatabaseTestClass.TestService.GenerateData();
}
}
Is there anyway to indicate that the DB should be flushed first (without manually calling DELETE FROM XX for every table), or is there a way I can pass through a command to do that for me?
The solution was as follows :
[AssemblyInitialize()]
public static void InitializeAssembly(TestContext ctx)
{
// Setup the test database based on setting in the
// configuration file
try
{
var conn = SqlDatabaseTestClass.TestService.OpenExecutionContext();
var cmd = conn.Connection.CreateCommand();
cmd.CommandText = "use master; ALTER DATABASE [MyTestDb] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;DROP DATABASE MyTestDb;";
cmd.ExecuteNonQuery();
}
catch
{
}
SqlDatabaseTestClass.TestService.DeployDatabaseProject();
SqlDatabaseTestClass.TestService.GenerateData();
}
I'm implementing NUnit Integration Tests of our controller REST endpoints in a .NET Web API 2 project. We use an Entity Framework code-first from database approach to create our controllers and models.
I've got the myProjectIntegrationTests project set up, with NUnit installed and a reference to myProject.
From my research, the next step is to create a TestSetup script which, on each test, creates an Integration Tests Database in a LocalDb. This allows us to integration test our API calls without affecting the master dev database.
This TestSetup script should do several things each time a test runs:
- check if a connection is currently open in Integration Test Db - if so, close it.
- check if an existing Integration Test db exists - if so, tear it down.
- run a migration from my master dev database to my Integration Test Db to load it with real data.
- create a new instance of Integration Test Db
- integration tests run...
- close Integration Test Db connections
- teardown Integration Test Db
Creating this TestSetup class is what's giving me trouble. I've found tutorials on how to do this for .NET MVC, .NET Core and also Entity Framework - but none of these seem to be utilizing just .Net Web API, so some of the libraries and code being referenced isn't working for me. Can someone provide an example script or tutorial link that might work in .NET Web API 2?
Here's an example of someone doing this for EntityFramework, using I believe .Net Core. This is part of a great PluralSight tutorial on integration testing in Entity Framework by Michael Perry, found here:
using Globalmantics.DAL;
using Globalmantics.DAL.Migrations;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Data.E ntity;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Globalmantics.IntegrationTests
{
[SetUpFixture]
public class TestSetup
{
[OneTimeSetUp]
public void SetUpDatabase()
{
DestroyDatabase();
CreateDatabase();
}
[OneTimeTearDown]
public void TearDownDatabase()
{
DestroyDatabase();
}
private static void CreateDatabase()
{
ExecuteSqlCommand(Master, $#"
CREATE DATABASE [Globalmantics]
ON (NAME = 'Globalmantics',
FILENAME = '{Filename}')");
var migration = new MigrateDatabaseToLatestVersion<
GlobalmanticsContext, GlobalmanticsConfiguration>();
migration.InitializeDatabase(new GlobalmanticsContext());
}
private static void DestroyDatabase()
{
var fileNames = ExecuteSqlQuery(Master, #"
SELECT [physical_name] FROM [sys].[master_files]
WHERE [database_id] = DB_ID('Globalmantics')",
row => (string)row["physical_name"]);
if (fileNames.Any())
{
ExecuteSqlCommand(Master, #"
ALTER DATABASE [Globalmantics] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
EXEC sp_detach_db 'Globalmantics'");
fileNames.ForEach(File.Delete);
}
}
private static void ExecuteSqlCommand(
SqlConnectionStringBuilder connectionStringBuilder,
string commandText)
{
using (var connection = new SqlConnection(connectionStringBuilder.ConnectionString))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = commandText;
command.ExecuteNonQuery();
}
}
}
private static List<T> ExecuteSqlQuery<T>(
SqlConnectionStringBuilder connectionStringBuilder,
string queryText,
Func<SqlDataReader, T> read)
{
var result = new List<T>();
using (var connection = new SqlConnection(connectionStringBuilder.ConnectionString))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = queryText;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
result.Add(read(reader));
}
}
}
}
return result;
}
private static SqlConnectionStringBuilder Master =>
new SqlConnectionStringBuilder
{
DataSource = #"(LocalDB)\MSSQLLocalDB",
InitialCatalog = "master",
IntegratedSecurity = true
};
private static string Filename => Path.Combine(
Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location),
"Globalmantics.mdf");
}
}
And here's an older example of someone doing this for .Net MVC:
using System;
using System.Data.Entity;
using NUnit.Framework;
namespace BankingSite.IntegrationTests
{
[SetUpFixture]
public class TestFixtureLifecycle
{
public TestFixtureLifecycle()
{
EnsureDataDirectoryConnectionStringPlaceholderIsSet();
EnsureNoExistingDatabaseFiles();
}
private static void EnsureDataDirectoryConnectionStringPlaceholderIsSet()
{
// When not running inside MVC application the |DataDirectory| placeholder
// is null in a connection string, e.g AttachDBFilename=|DataDirectory|\TestBankingSiteDb.mdf
AppDomain.CurrentDomain.SetData("DataDirectory", NUnit.Framework.TestContext.CurrentContext.TestDirectory);
}
private void EnsureNoExistingDatabaseFiles()
{
const string connectionString = "name=DefaultConnection";
if (Database.Exists(connectionString))
{
Database.Delete(connectionString);
}
}
}
}
Probably not the answer you are looking for but I have had success recently using the sql server docker image with docker compose.
You can fire up a database instance and delete the data volumes when the the image shuts down. Using the —rm switch on the docker run command will do that automatically for you.
If you are using dot net core you can setup another container to run your entity framework migrations and tests.
If you are using dotnet framework you maybe be able to run windows docker images however they tend to be a bit slower to startup.
This approach would work best if you launched everything from a powershell script. Launching the infrastructure from the code as you are looking to do could be tricky and perhaps more complex than it needs to be.
Going line-by-line through the type of sql commands you'll need for these operations is just going to be painful. You would benefit much better to just develop a stored procedure that does the tear-down/build-up steps. You appear to already have a start in that as I see you writing code around the statements. Then your integration test code would just need to call this procedure and wait for the setup to complete. Remember, You don't have to do everything in code.
I'm developing a software that will be used in different locations with different Servers. It differs in Server Name, Database name, etc.
Example:
Location 1 : Server Name: ChinaServer; Database Name: ChinaDB
Location 2 : Server Name: USServer; Database Name: USDB
Currently, I am using .ini file, I store the server name, database name and other configurations to it. I read it and use it runtime for my connection string. The problem here is that every time we switch locations, I need to change/edit the .ini file.
I'm asking everyone that has more experience that mine to give me other options or best approach on this matter.
Client's Environment : Windows 7
Developers : Windows 7, Visual Studio 2015, MS SQL, VB.NET
Thanks IA.
There's a couple of ways, each with their own advantages and disadvantages, the configuration file would work, could also store it in the registry of the server and read it that way. Or you could even use a My.Setting variable that can be updated in a settings page (probably not the most suitable for your situation)
You can get the basic idea from the The Twelve-Factor App "manifesto":
The twelve-factor app stores config in environment variables...
So what you need is to establish a machine-wide (setx /M NAME VALUE) environment variable which you'll later use like this:
var connectionString = Environment.GetEnvironmentVariable("MY_APP_CONNECTION_STRING");
var dbContext = new DbContext(connectionString);
You can use the SQL Server enumerator in System.Data.Sql, and run a query to get the database names. From there bind those lists to combo boxes, and use a SqlConnectionStringBuilder to keep track of your connection settings. You can save them to disk, or just ask the user to choose the server and database. Note that the enumerator is not guaranteed to always find all servers, so make sure you have a way to enter it manually if necessary.
private SqlConnectionStringBuilder _connString = new SqlConnectionStringBuilder();
private void RefreshConnectionString()
{
_connString.ApplicationName = AppDomain.CurrentDomain.ApplicationIdentity.FullName;
_connString.ApplicationIntent = ApplicationIntent.ReadWrite;
_connString.DataSource = GetSqlDatasources().FirstOrDefault();
_connString.InitialCatalog = GetSqlDatabases().FirstOrDefault();
_connString.AsynchronousProcessing = true;
_connString.ConnectTimeout = 5;
_connString.IntegratedSecurity = true;
_connString.Pooling = true;
}
private IEnumerable<string> GetSqlDatabases()
{
using (var conn = new SqlConnection(_connString.ConnectionString))
{
using (var cmd = new SqlCommand(#"SELECT [name] FROM sys.databases WHERE [name] NOT IN ('master', 'model', 'msdb', 'tempdb')", conn))
{
var dbnames = new List<string>();
try
{
conn.Open();
var reader = cmd.ExecuteReader();
while (reader.Read()) dbnames.Add(reader.GetString(0));
}
catch {}
return dbnames;
}
}
}
private IEnumerable<string> GetSqlDatasources()
{
var sqlEnum = SqlDataSourceEnumerator.Instance;
return sqlEnum.GetDataSources().Rows.OfType<DataRow>().Select(row => row[0].ToString());
}
I am trying my hands on Windows phone 8 applications and I am stuck into a weird situation here. I am using sqlite in order to create sqlite db and add values into the database. I am able to create the database and add the values in the database successfully but I am having a weird situation here.
Everytime I close the emulator and start the project again the database gets created again which should not be happening because I created the db the very first time I run the application.
Does anybody know why, and how I can prevent it from recreating the database each time?
public string DB_PATH = Path.Combine(Path.Combine(ApplicationData.Current.LocalFolder.Path, "aa.sqlite"));
private SQLiteConnection dtCon;
public MainPage()
{
InitializeComponent();
CreateDatabase();
dtCon = new SQLiteConnection(DB_PATH);
var tp = dtCon.Query<Contacts>("select * from contacts").ToList();
}
private async void CreateDatabase()
{
bool isDatabaseExisting = false;
//Checking if database already exists
try
{
Windows.Storage.StorageFile storagefile = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync("aa.sqlite");
isDatabaseExisting = true;
}
catch
{
isDatabaseExisting = false;
}
//if not exists then creating database
if (!isDatabaseExisting)
{
String str = System.IO.Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "sqlite.db");
AddDataToDB(DB_PATH);
}
}
private void AddDataToDB(string str)
{
// Create the database connection.
dtCon = new SQLiteConnection(str);
// Create the table Task, if it doesn't exist.
dtCon.CreateTable<Contacts>();
Contacts oContacts = new Contacts();
oContacts.Name = "dfgdf";
oContacts.Detail = "asdfsf";
dtCon.Insert(oContacts);
}
I'm pretty sure when you close your emulator and restart, you're basically just uninstalling the application. Which is why your files or not there anymore -- as it looks like you're storing your data in isolated storage. I do not know if there is anyway around this.
You can buy a very cheap Windows 8/8.1 Phone and the files will persist until you manually uninstall the test application.
As #Chubosaurus says, closing and re-opening the emulator will remove all the apps. You can generally keep it running as long as you want and keep re-deploying your app to the emulator (although obviously rebooting the host PC will kill it).
You can save and restore the data from your emulator image via the ISETool command. See more here
Try adding Console.WriteLine("True"); and Console.WriteLine("False"); into the expected places after checking isDatabaseExisting to see/understand what the code path really is.
I am trying to deploy an instance which is getting the following build error on App Harbor
Build FAILED.
"D:\temp\gcp22bmp.ggi\input\src\ShareBill.sln" (default target) (1) ->
"D:\temp\gcp22bmp.ggi\input\src\Sharebill.Database\Sharebill.Database.dbproj" (default target) (5) ->
D:\temp\gcp22bmp.ggi\input\src\packages\TeamData\Microsoft.Data.Schema.SqlTasks.targets(5,3): error MSB4019: The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\TeamData\Microsoft.Data.Schema.TSqlTasks.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk. [D:\temp\gcp22bmp.ggi\input\src\Sharebill.Database\Sharebill.Database.dbproj]
0 Warning(s)
1 Error(s)
I know this is because the sql targets that are generally present here - C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\TeamData
are not present on the deployment server.
What should I do to deploy the data base now? Is there any other way to deploy the database. I have not used code first in EF, but I still want to have db migrations automatically applied.
I am assuming that if i get the db project running it would automatically find the schema differences and apply the changes to the database.
I host a project on AppHarbor and use FluentMigrator to deploy my database changes.
It is really easy to implement, just follow the documentation you can use their fluent interface or even just use it to execute sql.
As an example I run the following from my Application_Start of my Global.asax.cs - just put you migrations in the same assembly as the NOP MigrationMarker class:
const string connectionString = #"Data Source=localhost, 1433;Initial Catalog=testdb;Integrated Security=SSPI;";
Announcer announcer = new TextWriterAnnouncer(s => System.Diagnostics.Debug.WriteLine(s));
announcer.ShowSql = true;
var assembly = Assembly.GetAssembly(typeof(MigrationMarker));
var migrationContext = new RunnerContext(announcer);
var options = new ProcessorOptions
{
PreviewOnly = false, // set to true to see the SQL
Timeout = 60
};
var factory = new SqlServer2008ProcessorFactory();
var processor = factory.Create(connectionString, announcer, options);
var runner = new MigrationRunner(assembly, migrationContext, processor);
runner.MigrateUp(true);