From e5b0ccbfc5b8fd80ec26b1d51d076bfde944ce09 Mon Sep 17 00:00:00 2001 From: Vikas Negi <68782261+vnegi10@users.noreply.github.com> Date: Sat, 30 Jul 2022 23:02:32 +0200 Subject: [PATCH] Update test framework (#19) * Split tests into separate files * Add tests for AV plots * Add tests for CG plots * Update tests * Bump minor version --- Project.toml | 2 +- test/Project.toml | 1 + test/runtests.jl | 140 +++++++++--------------------------- test/test_API_CG.jl | 65 +++++++++++++++++ test/test_marketdata_AV.jl | 26 +++++++ test/test_movingaverages.jl | 28 ++++++++ test/test_plots_AV.jl | 87 ++++++++++++++++++++++ test/test_plots_CG.jl | 33 +++++++++ 8 files changed, 274 insertions(+), 108 deletions(-) create mode 100644 test/test_API_CG.jl create mode 100644 test/test_marketdata_AV.jl create mode 100644 test/test_movingaverages.jl create mode 100644 test/test_plots_AV.jl create mode 100644 test/test_plots_CG.jl diff --git a/Project.toml b/Project.toml index c5192b2..9e50dbf 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "CryptoDashApp" uuid = "8f55a569-a1ee-45d2-b761-b2b316ddd8e9" authors = ["Vikas Negi "] -version = "0.2.2" +version = "0.3.0" [deps] AlphaVantage = "6348297c-a006-11e8-3a05-9bbf8830fd7b" diff --git a/test/Project.toml b/test/Project.toml index f1e81a7..2640031 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -4,5 +4,6 @@ DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a" Query = "1a8c2f83-1ff3-5112-b086-8aa67b057ba1" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/runtests.jl b/test/runtests.jl index df0f53f..fd5e98c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,5 @@ -using Test, AlphaVantage, Dates, DataFrames, CryptoDashApp, HTTP, JSON, Query +using Test, AlphaVantage, Dates, DataFrames, CryptoDashApp, + HTTP, JSON, Query, PlotlyJS AlphaVantage.global_key!("AKTJ25ALEBBLH1QJ") @@ -10,127 +11,52 @@ else @info "New data folder has been created" end -# Perform cleanup +# Perform cleanup of old data CryptoDashApp.remove_old_files() -################# Test cases for accessing market data ################# - -@testset "Check if AV market data are accessible" begin - - for currency in ["ETH", "LTC", "LINK"] - - df_out_price, df_out_candle, df_out_vol = - CryptoDashApp.get_price_data_single(currency) - - @test ~isempty(df_out_price) - @test ~isempty(df_out_candle) - @test ~isempty(df_out_vol) - - end - -end - -@testset "Check for exception handling while accessing AV market data" begin - - currency = "dummy" - - @test_logs (:info, "Could not fetch data, try again later!") match_mode = :any CryptoDashApp.get_price_data_single( - currency, - ) - -end - -################# Test cases for moving averages ################# - -@testset "Check if MA, MACD + signal, σ (for Bollinger bands) are calculated" begin - - for currency in ["BTC", "DOT"] - - df_out_price, _, _ = CryptoDashApp.get_price_data_single(currency) - - duration = 90 - window = 30 - - price_SMA, price_WMA, price_EMA = - CryptoDashApp.moving_averages(df_out_price, duration, window) - - @test ~isempty(price_SMA) - @test ~isempty(price_WMA) - @test ~isempty(price_WMA) - - df_out_price = df_out_price[end-duration+1-26-9+1:end, :] - df_ema_all = CryptoDashApp.calculate_macd(df_out_price) - @test ~isempty(df_ema_all) - - Price_σ = CryptoDashApp.moving_std(df_out_price, duration, window) - @test ~isempty(Price_σ) - - end +errors = false +all_tests = false +# Run all tests when no arguments or "all" is specified +if isempty(ARGS) || "all" in ARGS + all_tests = true end -################# Test cases for CoinGecko API ################# - -@testset "Check if CG developer and community data are accessible" begin - - for currency in ["btc", "eth", "ltc"] - - df_dev, df_comm = CryptoDashApp.get_dev_comm_data(currency) - - @test ~isempty(df_dev) - @test ~isempty(df_comm) +# Execute test in a try-catch block for each file +function execute_test(file::String, ARGS; all_tests::Bool, errors::Bool) + if all_tests || file in ARGS + try + include(file) + println("\t\033[1m\033[32mPASSED\033[0m: $(file)") + catch e + println("\t\033[1m\033[31mFAILED\033[0m: $(file)") + errors = true + showerror(stdout, e, backtrace()) + println() + end end -end - -@testset "Check for exception handling while determining coin id" begin - - currency = "dummy" - - @test_logs (:info, "Could not find an id for the given currency") match_mode = :any CryptoDashApp.get_coin_id( - currency, - ) - -end - -@testset "Check if CG exchange volume data per currency are accessible" begin - - for currency in ["btc", "eth", "ltc"] - - num_exchanges = 10 - - df_ex_vol = CryptoDashApp.get_exchange_vol_data(currency, num_exchanges) - - @test size(df_ex_vol)[1] == num_exchanges - + if errors + @warn "Some tests have failed! Check the results summary above." end - end -@testset "Check if CG overall exchange volume data are accessible" begin - num_exchanges = 10 +################# All test groups ################# - for duration in [5, 10, 50, 75] - df_ex_vol = CryptoDashApp.get_overall_vol_data(duration, num_exchanges) +test_files = ["test_API_CG.jl", + "test_marketdata_AV.jl", + "test_movingaverages.jl", + "test_plots_AV.jl", + "test_plots_CG.jl"] - # Check for rows - @test size(df_ex_vol)[1] == duration +################################################### - # Check for columns, total is num_exchanges + 1 due to "Time" column - @test size(df_ex_vol)[2] == num_exchanges + 1 - end +################# Execute tests ################### +@time for file in test_files + execute_test(file, ARGS, all_tests = all_tests, errors = errors) end -#=@testset "Check if ratings data is accessible" begin - - utility_score, fcas_score, dev_score, mark_score, fcas_rating = CryptoDashApp.get_ratings_data("ETH") - - @test ~isempty(utility_score) - @test ~isempty(fcas_score) - @test ~isempty(dev_score) - @test ~isempty(mark_score) - @test ~isempty(fcas_rating) -end=# \ No newline at end of file +################################################### \ No newline at end of file diff --git a/test/test_API_CG.jl b/test/test_API_CG.jl new file mode 100644 index 0000000..5397049 --- /dev/null +++ b/test/test_API_CG.jl @@ -0,0 +1,65 @@ +################# Test cases for CoinGecko API ################# + +@testset "Check if CG developer and community data are accessible" begin + + for currency in ["btc", "eth", "ltc"] + + df_dev, df_comm = CryptoDashApp.get_dev_comm_data(currency) + + @test ~isempty(df_dev) + @test ~isempty(df_comm) + + end + +end + +@testset "Check for exception handling while determining coin id" begin + + currency = "dummy" + + @test_logs (:info, "Could not find an id for the given currency") match_mode = :any CryptoDashApp.get_coin_id( + currency, + ) + +end + +@testset "Check if CG exchange volume data per currency are accessible" begin + + for currency in ["btc", "eth", "ltc"] + + num_exchanges = 10 + + df_ex_vol = CryptoDashApp.get_exchange_vol_data(currency, num_exchanges) + + @test size(df_ex_vol)[1] == num_exchanges + + end + +end + +@testset "Check if CG overall exchange volume data are accessible" begin + + num_exchanges = 10 + + for duration in [5, 10, 50, 75] + df_ex_vol = CryptoDashApp.get_overall_vol_data(duration, num_exchanges) + + # Check for rows + @test size(df_ex_vol)[1] == duration + + # Check for columns, total is num_exchanges + 1 due to "Time" column + @test size(df_ex_vol)[2] == num_exchanges + 1 + end + +end + +#=@testset "Check if ratings data is accessible" begin + + utility_score, fcas_score, dev_score, mark_score, fcas_rating = CryptoDashApp.get_ratings_data("ETH") + + @test ~isempty(utility_score) + @test ~isempty(fcas_score) + @test ~isempty(dev_score) + @test ~isempty(mark_score) + @test ~isempty(fcas_rating) +end=# \ No newline at end of file diff --git a/test/test_marketdata_AV.jl b/test/test_marketdata_AV.jl new file mode 100644 index 0000000..b82cf52 --- /dev/null +++ b/test/test_marketdata_AV.jl @@ -0,0 +1,26 @@ +################# Test cases for accessing market data ################# + +@testset "Check if AV market data are accessible" begin + + for currency in ["ETH", "LTC", "LINK"] + + df_out_price, df_out_candle, df_out_vol = + CryptoDashApp.get_price_data_single(currency) + + @test ~isempty(df_out_price) + @test ~isempty(df_out_candle) + @test ~isempty(df_out_vol) + + end + +end + +@testset "Check for exception handling while accessing AV market data" begin + + currency = "dummy" + + @test_logs (:info, "Could not fetch data, try again later!") match_mode = :any CryptoDashApp.get_price_data_single( + currency, + ) + +end \ No newline at end of file diff --git a/test/test_movingaverages.jl b/test/test_movingaverages.jl new file mode 100644 index 0000000..ac5eb08 --- /dev/null +++ b/test/test_movingaverages.jl @@ -0,0 +1,28 @@ +################# Test cases for moving averages ################# + +@testset "Check if MA, MACD + signal, σ (for Bollinger bands) are calculated" begin + + for currency in ["BTC", "DOT"] + + df_out_price, _, _ = CryptoDashApp.get_price_data_single(currency) + + duration = 90 + window = 30 + + price_SMA, price_WMA, price_EMA = + CryptoDashApp.moving_averages(df_out_price, duration, window) + + @test ~isempty(price_SMA) + @test ~isempty(price_WMA) + @test ~isempty(price_WMA) + + df_out_price = df_out_price[end-duration+1-26-9+1:end, :] + df_ema_all = CryptoDashApp.calculate_macd(df_out_price) + @test ~isempty(df_ema_all) + + Price_σ = CryptoDashApp.moving_std(df_out_price, duration, window) + @test ~isempty(Price_σ) + + end + +end \ No newline at end of file diff --git a/test/test_plots_AV.jl b/test/test_plots_AV.jl new file mode 100644 index 0000000..332a726 --- /dev/null +++ b/test/test_plots_AV.jl @@ -0,0 +1,87 @@ +################# Test cases for plots using AlphaVantage data ################# + +@testset "plot_price_ma_trade_data" begin + + all_traces = CryptoDashApp.plot_price_ma_trade_data(7, 90, 30) + @test ~isempty(all_traces) + + for trace in all_traces + @test trace.fields[:y] |> length == 90 + end + +end + +@testset "plot_price_bollinger_bands" begin + + all_traces = CryptoDashApp.plot_price_bollinger_bands(13, 180, 30) + @test ~isempty(all_traces) + + for trace in all_traces + @test trace.fields[:y] |> length == 180 + end + +end + +@testset "plot_candle_vol_data" begin + + all_traces = CryptoDashApp.plot_candle_vol_data(18, 180) + @test ~isempty(all_traces) + + # Check candlestick data + candle_trace = all_traces[1] + + for candle in [:high, :low, :open, :close] + @test candle_trace.fields[candle] |> length == 180 + end + + bar_trace = all_traces[2] + @test bar_trace.fields[:y] |> length == 180 + +end + +@testset "plot_cumul_daily_return_hist" begin + + all_traces = CryptoDashApp.plot_cumul_daily_return_hist(12, 60) + @test ~isempty(all_traces) + + # Cumulative return + @test all_traces[1].fields[:y] |> length == 59 + + # Green and red returns will change with time, hence cannot be tested here + + # Daily change histogram + @test all_traces[4].fields[:y] |> length == 78 + +end + +@testset "plot_fcas_data" begin + + trace1 = CryptoDashApp.plot_fcas_data(13)[1] + + # Unable to get FCAS metrics from AV, so skipping tests for now [30-07-2022] + @test_skip ~isempty(trace1) + @test_skip typeof(trace1) == PlotlyBase.GenericTrace{Dict{Symbol, Any}} + +end + +@testset "plot_macd_signal" begin + + all_traces = CryptoDashApp.plot_macd_signal(2, 42) + @test ~isempty(all_traces) + + for trace in all_traces + trace.fields[:y] |> length == 43 + end + +end + +@testset "plot_linear_regression" begin + + all_traces = CryptoDashApp.plot_linear_regression(17, 200) + @test ~isempty(all_traces) + + for trace in all_traces[1:4] + @test trace.fields[:y] |> length == 200 + end + +end \ No newline at end of file diff --git a/test/test_plots_CG.jl b/test/test_plots_CG.jl new file mode 100644 index 0000000..432f47b --- /dev/null +++ b/test/test_plots_CG.jl @@ -0,0 +1,33 @@ +################# Test cases for plots using CoinGecko data ################# + +@testset "plot_dev_comm_data" begin + + all_traces = CryptoDashApp.plot_dev_comm_data(7) + @test ~isempty(all_traces) + + @test all_traces[1].fields[:y] |> length == 8 + @test all_traces[2].fields[:y] |> length == 5 + +end + +@testset "plot_exchange_vol_data" begin + + all_traces = CryptoDashApp.plot_exchange_vol_data(7) + @test ~isempty(all_traces) + + for trace in all_traces + @test trace.fields[:y] |> length == 10 + end + +end + +@testset "plot_overall_vol_data" begin + + all_traces = CryptoDashApp.plot_overall_vol_data(30) + @test ~isempty(all_traces) + + for trace in all_traces + @test trace.fields[:y] |> length == 30 + end + +end \ No newline at end of file