What is a uvm test?

A uvm_test is a key component of the testbench used to define and orchestrate the verification sequences and tests that verify the functionality of the design under test (DUT). The uvm_test serves as the starting point for the verification process, and it is responsible for creating and managing the execution of test sequences, coordinating interactions with the DUT, and collecting the results of the verification.

uvm_test is a actual class from where we see the testbench creation, configuration and sequence driving. In essence this is the class which acts as the starting point of a uvm testbench.

Code
// Filename : basic_test.sv

class sample_base_test extends uvm_test;
    `uvm_component_utils(sample_base_test)

    uvm_root                        top;
    basic_env                        env;
    basic_sequence                basic_seq;

    extern         function      new(string name, uvm_component parent);
    extern virtual function void build_phase(uvm_phase phase);
    extern virtual function void connect_phase(uvm_phase phase);
    extern virtual function void end_of_elaboration_phase(uvm_phase phase);
    extern virtual function void start_of_simulation_phase(uvm_phase phase);
    extern virtual task  main_phase(uvm_phase phase);

    extern virtual function void extract_phase(uvm_phase phase);
    extern virtual function void check_phase(uvm_phase phase);
    extern virtual function void report_phase(uvm_phase phase);
    extern virtual function void final_phase(uvm_phase phase);

endclass: sample_base_test

//---------------------------------------------------------------------//

function sample_base_test::new(string name, uvm_component parent);
    super.new(name, parent);

endfunction: new

//------------------------------------------------------------------//

function void sample_base_test::build_phase(uvm_phase phase);
    super.build_phase(phase);

    top = uvm_root::get();

    env = basic_env::type_id::create("env", this);
endfunction: build_phase

//------------------------------------------------------------------//

function void sample_base_test::connect_phase(uvm_phase phase);
    super.connect_phase(phase);

endfunction: connect_phase

//------------------------------------------------------------------//

function void sample_base_test::end_of_elaboration_phase(uvm_phase phase);
    super.end_of_elaboration_phase(phase);

endfunction: end_of_elaboration_phase

//------------------------------------------------------------------//

function void sample_base_test::start_of_simulation_phase(uvm_phase phase);
    super.start_of_simulation_phase(phase);

endfunction: start_of_simulation_phase

//------------------------------------------------------------------//

task sample_base_test::main_phase(uvm_phase phase);
    super.main_phase(phase);
    phase.raise_objection(this);

    basic_seq = basic_sequence::type_id::create("basic_seq", this);

    phase.drop_objection(this);
endtask: main_phase

//------------------------------------------------------------------//

function void sample_base_test::extract_phase(uvm_phase phase);
    super.extract_phase(phase);

endfunction: extract_phase

//------------------------------------------------------------------//

function void sample_base_test::check_phase(uvm_phase phase);
    super.check_phase(phase);

endfunction: check_phase

//------------------------------------------------------------------//

function void sample_base_test::report_phase(uvm_phase phase); uvm_factory factory=uvm_factory::get();
    super.report_phase(phase);

endfunction: report_phase

//------------------------------------------------------------------//

function void sample_base_test::final_phase(uvm_phase phase);
    super.final_phase(phase);

endfunction: final_phase
Code
// Filename : sanity_test.sv

class sample_sanity_test extends sample_base_test;
	`uvm_component_utils(sample_sanity_test)

	extern         function      new(string name, uvm_component parent);
	extern virtual function void build_phase(uvm_phase phase);
	extern virtual function void connect_phase(uvm_phase phase);
	extern virtual function void end_of_elaboration_phase(uvm_phase phase);
	extern virtual task          main_phase(uvm_phase phase);
	
endclass

//--------------------------------------------------------------//

function sample_sanity_test::new(string name, uvm_component parent);
	super.new(name, parent);

endfunction: new

//--------------------------------------------------------------//

function void sample_sanity_test::build_phase(uvm_phase phase);
	super.build_phase(phase);

endfunction: build_phase

//--------------------------------------------------------------//

function void sample_sanity_test::connect_phase(uvm_phase phase);
	super.connect_phase(phase);

endfunction: connect_phase

//--------------------------------------------------------------//

function void sample_sanity_test::end_of_elaboration_phase(uvm_phase phase);
	super.end_of_elaboration_phase(phase);

endfunction: end_of_elaboration_phase

//--------------------------------------------------------------//

task sample_sanity_test::main_phase(uvm_phase phase);
	super.main_phase(phase);        
	phase.raise_objection(this);

    basic_seq.start(env.basic_seqr);

	phase.drop_objection(this);
endtask: main_phase
Theory Questions
    You can select a uvm_test to run by using the +UVM_TESTNAME command-line option. For example, +UVM_TESTNAME=my_test would run the my_test class, which extends uvm_test.
    No, only one uvm_test can be instantiated in a UVM testbench at a time. This is because the uvm_test is the top-level test component, and UVM is designed to have a single test controlling the execution at any given time. Although this is not a hard and fast rule, but it is considered as part of the methodology. The alternative is to instantiate a other tests inside the main test and then use that test's methods and environment.
    Configuration parameters can be passed to a uvm_test using the UVM configuration database (uvm_config_db). The parameters can be set in the uvm_test or another higher-level component and retrieved in the uvm_test or any lower-level component. Alternatively, you can pass configurats using basic component level heirarchical access from systemverilog, ie using the dot (.) operator.
    The run_test() function is used to start the UVM testbench simulation. It automatically creates and runs the uvm_test specified by the +UVM_TESTNAME command-line option. If no test is specified, it defaults to the test specified in the code by calling run_test("test_name").
    You can ensure a specific uvm_test runs by either specifying it using the +UVM_TESTNAME=test_name command-line option or by explicitly calling run_test("test_name") in the top-level module.