| | | 1 | | namespace ZhEaIsNsAaBn.IntegrationTestingBases; |
| | | 2 | | |
| | | 3 | | /// <summary>Random values for test data. Uses <see cref="Random.Shared"/>, so it is safe in parallel tests. Not for sec |
| | | 4 | | public static class TestDataGenerator |
| | | 5 | | { |
| | | 6 | | private const string Characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; |
| | | 7 | | |
| | | 8 | | |
| | | 9 | | /// <summary>Creates a random string of letters and digits.</summary> |
| | | 10 | | /// <param name="length">The string length.</param> |
| | | 11 | | /// <returns>The random string.</returns> |
| | 9 | 12 | | public static string RandomString( int length ) => new( Random.Shared.GetItems( Characters.AsSpan(), length ) ); |
| | | 13 | | |
| | | 14 | | /// <summary>Creates a random lower-case email address, e.g. <c>abcd1234@xyz123.com</c>.</summary> |
| | | 15 | | /// <returns>The email address.</returns> |
| | 3 | 16 | | public static string RandomEmail() => $"{RandomString( 8 ).ToLowerInvariant()}@{RandomString( 6 ).ToLowerInvariant() |
| | | 17 | | |
| | | 18 | | /// <summary>Creates a random integer.</summary> |
| | | 19 | | /// <param name="min">Inclusive lower bound. Default: <c>1</c>.</param> |
| | | 20 | | /// <param name="max">Exclusive upper bound. Default: <c>1000</c>.</param> |
| | | 21 | | /// <returns>A value from <paramref name="min"/> up to, not including, <paramref name="max"/>.</returns> |
| | 600 | 22 | | public static int RandomInt( int min = 1, int max = 1000 ) => Random.Shared.Next( min, max ); |
| | | 23 | | |
| | | 24 | | /// <summary>Creates a random decimal.</summary> |
| | | 25 | | /// <param name="min">Inclusive lower bound. Default: <c>1</c>.</param> |
| | | 26 | | /// <param name="max">Upper bound. Default: <c>1000</c>.</param> |
| | | 27 | | /// <returns>A value between <paramref name="min"/> and <paramref name="max"/>.</returns> |
| | | 28 | | public static decimal RandomDecimal( decimal min = 1, decimal max = 1000 ) |
| | 0 | 29 | | => (decimal) ( ( Random.Shared.NextDouble() * (double) ( max - min ) ) + (double) min ); |
| | | 30 | | |
| | | 31 | | /// <summary>Creates a random boolean.</summary> |
| | | 32 | | /// <returns><see langword="true"/> or <see langword="false"/>.</returns> |
| | 0 | 33 | | public static bool RandomBool() => Random.Shared.Next( 2 ) == 1; |
| | | 34 | | |
| | | 35 | | /// <summary>Creates a random local date and time.</summary> |
| | | 36 | | /// <param name="minDate">Lower bound. Default: five years ago.</param> |
| | | 37 | | /// <param name="maxDate">Upper bound. Default: five years from now.</param> |
| | | 38 | | /// <returns>A value between <paramref name="minDate"/> and <paramref name="maxDate"/>.</returns> |
| | | 39 | | public static DateTime RandomDate( DateTime? minDate = null, DateTime? maxDate = null ) |
| | | 40 | | { |
| | 3 | 41 | | var min = minDate ?? DateTime.Now.AddYears( -5 ); |
| | 3 | 42 | | var max = maxDate ?? DateTime.Now.AddYears( 5 ); |
| | 3 | 43 | | var range = max - min; |
| | | 44 | | |
| | | 45 | | |
| | 3 | 46 | | return min + new TimeSpan( (long) ( Random.Shared.NextDouble() * range.Ticks ) ); |
| | | 47 | | } |
| | | 48 | | |
| | | 49 | | /// <summary>Picks a random item.</summary> |
| | | 50 | | /// <typeparam name="T">The item type.</typeparam> |
| | | 51 | | /// <param name="items">The items to pick from.</param> |
| | | 52 | | /// <returns>One of <paramref name="items"/>.</returns> |
| | | 53 | | /// <exception cref="ArgumentException"><paramref name="items"/> is empty.</exception> |
| | | 54 | | public static T RandomItem< T >( IEnumerable<T> items ) |
| | | 55 | | { |
| | 6 | 56 | | var list = items as IReadOnlyList<T> ?? [ .. items ]; |
| | | 57 | | |
| | 9 | 58 | | if ( list.Count == 0 ) { throw new ArgumentException( "The collection is empty.", nameof(items) ); } |
| | | 59 | | |
| | | 60 | | |
| | 3 | 61 | | return list[ Random.Shared.Next( list.Count ) ]; |
| | | 62 | | } |
| | | 63 | | } |